通过LightSwitch ServerApplicationContext 和WebAPI 获取用户权限

[原文发表地址] Using LightSwitch ServerApplicationContext and WebAPI to Get User Permissions

[原文发表时间] 2013-4-17 12:36 PM

上一篇博文中,我向大家介绍了通过HTML客户端界面检查单个用户权限的简便方法,以此禁用/启用 UI 元素。如果你只想查看两个权限而且也不想去写一堆代码,那么这个简单的窍门很适合你。但是,如果你想通过客户端HTML应用程序来查看很多权限,或者你需要向自己在LightSwitch服务器上创建的自定义web客户端返回用户权限时,更好的办法就是为登录的用户一次性获取所有的权限并将这些权限存储在客户端,这样的话在任意界面都能获取它们而不用再去访问数据库。

LightSwitch的基本原理是为快速创建企业应用程序提供RAD 工具,但仍然在需要时允许随时随地高级自定义设置。在这篇博文中我将向大家演示如何通过Web API和LightSwitch ServerApplicationContext(这个我已经在Visual Studio 2012 更新 2介绍过)创建一个自定义网站,从而返回用户权限。如果不记得Matt有关于此的博文,请查看:应用 the LightSwitch ServerApplicationContext API。

你可以在这里下载文中的示例代码。

创建权限和提高数据安全性

提高基于用户权限的数据安全性的第一步就是定义你的权限并且通过全局访问控制方法来查看权限。举个例子,我们要创建两个权限“CanAddCustomer”和“CanEditCustomer”来决定用户是否可以对服务器上的自定义实体进行插入和编辑操作。

打开Project Properties,定义你的权限。确保能够认证,然后勾选调试时需要启用的权限。

clip_image001

在data designer选择Server perspective,然后打开Write Code的下拉菜单并选择Customers_CanInsert和Customers_CanUpdate这两个访问控制方法。

clip_image002

然后编写如下代码来允许或者不允许用户的插入和编辑操作。

VB:

 Private Sub Customers_CanInsert(ByRef result As Boolean)
     result = Me.Application.User.HasPermission(Permissions.CanAddCustomer)
 End Sub
  
 Private Sub Customers_CanUpdate(ByRef result As Boolean)
     result = Me.Application.User.HasPermission(Permissions.CanEditCustomer)
 End Sub

C#:

 partial void Customers_CanInsert(ref bool result)
 {
     result = this.Application.User.HasPermission(Permissions.CanAddCustomer);
 }
  
 partial void Customers_CanUpdate(ref bool result)
 {
     result = this.Application.User.HasPermission(Permissions.CanEditCustomer);
 }

人们一直想要用这种方法提高服务器端代码安全性从而保护系统数据。但是,有时候我们也想要在UI上得到许可来隐藏/显示(或者启用/禁用)众多屏幕中的一些元素。

就像我在上一篇博文中提到的,Silverlight桌面客户端在任意屏幕且一直都给你暴露着一个可用的用户对象,所以很容易就能够在客户端查看权限。接下来介绍如何为保存着登陆用户权限的客户端HTML创建一个相似的对象。

在LightSwitch 服务端创建自定义Web API

首先,我们要采用Web API暴露一个向客户端返回JSON的Restful服务。跳转到Solution Explorer的File View。

clip_image003

向Server project添加一个名为“Perms”(你也可以随便命名)的文件,添加一个新项目,选择Web API Controller Class命名为“UserPermissionsController”。

clip_image004

现在我们可以用LightSwitch ServerApplicationContext来验证用户已经通过认证并为他们自身创建权限字典。如果用户没有得到认证,那么不返回任何东西。注意你得先向LightSwitch 服务端添加引用且加强命名空间安全性。

为了查询权限数据所在的LightSwitch安全数据,我们需要暂时提高请求者的权限。这个提升仅在方法执行过程中有效。如需获知更多关于权限提升的信息请参考: 如何在服务端代码提升权限

仔细核实你存入字典的权限。这里我们将简单地发布一系列权限,我们不会放入任何诸如用户名或密码这类的敏感信息。请记住权力与责任并存。

VB:

 Imports System.Net
 Imports System.Web.Http
 Imports LightSwitchApplication
 Imports Microsoft.LightSwitch.Server
 Imports Microsoft.LightSwitch.Security
  
 Public Class UserPermissionsController
     Inherits ApiController
  
     ' GET api/<controller>
     Public Function GetValues() As Dictionary(Of String, Boolean)
         'This will generically retrieve all the permissions of the current logged in user. 
  
         Dim perms As New Dictionary(Of String, Boolean)
  
         Using ctx As ServerApplicationContext = ServerApplicationContext.CreateContext()
             Dim currentUser = ctx.Application.User
  
             'If the requestor is not logged in then nothing is returned. 
             ' Only properly logged in users can retrieve their own permissions
             If currentUser.IsAuthenticated Then
  
                 perms.Add(Permissions.SecurityAdministration,
                           currentUser.HasPermission(Permissions.SecurityAdministration))
  
                 'elevate permissions temporarily
                 currentUser.AddPermissions(Permissions.SecurityAdministration)
  
                 For Each perm As Permission In ctx.DataWorkspace.SecurityData.Permissions()
                     If perm.Id <> Permissions.SecurityAdministration Then
  
                         perms.Add(perm.Id, currentUser.HasPermission(perm.Id))
                     End If
                 Next
             End If
         End Using
  
         Return perms
     End Function
  
 End Class

C#:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Net;
 using System.Net.Http;
 using System.Web.Http;
 using Microsoft.LightSwitch.Server;
 using Microsoft.LightSwitch.Security;
 using Microsoft.LightSwitch.Security.Server;
 using LightSwitchApplication;
  
 namespace LightSwitchApplication.Perms
 {
     public class UserPermissionsController : ApiController
     {
         // GET api/<controller>
         public Dictionary<string, Boolean> Get()
         {
             Dictionary<string, Boolean> perms = new Dictionary<string, Boolean>();
  
             using (ServerApplicationContext ctx = ServerApplicationContext.CreateContext())
             {
                 var currentUser = ctx.Application.User;
                 if (currentUser.IsAuthenticated)
                 {
                     perms.Add(Permissions.SecurityAdministration,
                         currentUser.HasPermission(Permissions.SecurityAdministration));
  
                     currentUser.AddPermissions(Permissions.SecurityAdministration);
  
                     foreach (Permission perm in ctx.DataWorkspace.SecurityData.Permissions)
                     {
                         if (perm.Id != Permissions.SecurityAdministration)
                         {
                             perms.Add(perm.Id, currentUser.HasPermission(perm.Id));
                         }
                     }
                 }
             }
             return perms;
         }
     }
 }

最后我们需要在控制器中添加一个路由。再一次右击Server Project,添加一个Global Application Class (Global.asax)并在头部添加如下引用:

VB:

 Imports System.Web.Http
 Imports System.Web.Routing

C#:

 using System.Web.Routing;
 using System.Web.Http; 

接着在Application_Start方法中添加路由。

VB:

 Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
     ' Fires when the application is started
     RouteTable.Routes.MapHttpRoute("PermsApi", "Perms/{controller}")
 End Sub

C#:

 protected void Application_Start(object sender, EventArgs e)
 {
     RouteTable.Routes.MapHttpRoute("PermsApi", "Perms/{controller}");
 }

在客户端获取权限

接下来我们需要在客户端调用这个方法并在全局对象中保存这个数据。在LightSwitch客户端HTML中有一个名为myapp的全局对象。我们可以用myapp来存储权限对象。你可以采用多种方法使用myapp对象来访问客户端HTML中的数据和界面。其它应用参考: 如何采用代码编辑NK "ht

存放获取权限代码最便捷的地方就是在我们应用程序第一个界面的created方法中。这是当App开始运行并且我们确定LightSwitch客户端环境已经就绪后调用的第一个用户方法。

打开你设置的主界面(很可能是你创建的第一个界面或者你可以在Solution Explorer的某个界面右击“Set as Home Screen”)。在树目录的顶部选择Screen node(界面节点),点击“Write Code”下拉框,选择created方法。

clip_image005

下面代码可实现调用web API并返回携带权限信息的JSON对象。

 myapp.BrowseCustomers.created = function (screen) {
     // Write code here.
     $.getJSON("../Perms/UserPermissions/", function (data) {
  
         //attach the permissions to the global 'myapp' object 
         //so it is accessible to the client anywhere.
         myapp.permissions = data;
      });    
 };

在此处设置一个断点,注意当你跑这段程序时会返回一个权限字典。

clip_image006

在JavaScript代码中查看权限

既然我们在客户端有权限集,我们可以在HTML界面的任意地方通过写一个简单的JavaScript来查看权限信息。在我的示例中,启用/禁用屏幕按钮取决于用户是否有添加或编辑客户端。

首先注意你要操作的控制器名称。在我的示例中我有AddCustomer和EditCustomer这两个按钮。

clip_image007

与之前一样,在树目录顶部选择Screen node(界面节点),点击“Write Code”下拉框,选择created方法。然后加入下面代码来查看权限对象。

 if (myapp.permissions["LightSwitchApplication:CanAddCustomer"]) {
     screen.findContentItem("AddCustomer").isEnabled = true;
 }
 else {
     screen.findContentItem("AddCustomer").isEnabled = false;
 }
 if (myapp.permissions["LightSwitchApplication:CanEditCustomer"]) {
     screen.findContentItem("EditCustomer").isEnabled = true;
 }
 else {
     screen.findContentItem("EditCustomer").isEnabled = false;
 }

现在我们可以看到这两个按钮可以基于权限正确的启用&禁用。

禁用。

clip_image001[7]

提要

总之,LightSwitch是提升效率的工具,我们致力于为开发者尽可能快地创建商业应用程序提供最好的用户体验。但是我们也想提供给用户高级的自定义功能和你随时随地可能需要的权力。无论你想要实现用户自定义控制、数据源、Web Services等等,这里都有很大扩展空间,尤其是在LightSwitch in Visual Studio 2012 Update 2最新版本(V3)中。

既然我们已经采用ServerApplicationContext向大家开放了服务器端的LightSwitch API,那么对大家来说,就创造了更多可能。伴随着Web API的易操作性,你可以向你的LightSwitch服务器logic提供自定义服务界面从而为大量客户提供灵活的、可自定义的、RESTful的HTTP 服务。

用这个实际的例子,希望不仅向大家展示如何获取用户权限,并且能起到抛砖引玉的作用。如需获取诸如dashboards和reporting scenarios等方面的更多示例,请继续关注 LightSwitch 团队博客

玩得愉快!