[WCF权限控制]ASP.NET Roles授权[上篇]

在采用Windows认证的情况下,使用基于Windows用户组安全主体权限模式是一个不错的选择。我们可以直接使用现有的用户组设置,也可以为相应的应用或服务创建单独的用户组。但是,由于该模式对Windows认证的依赖,意味着这种模式只能使用于局域网环境中。如果采用证书和Windows帐号的映射,也可以适用于像B2B这样的外部网环境。在其他的网络环境中,基于Windows用户组的授权方式将会无能为力。此外,还具有这样一种状况:即使是在同一个局域网环境中,并且也采用Windows进行客户端认证,但是我们不想创建太多的Windows用户组,而是将用户的权限信息维护在相应的数据库中,通过单独的安全系统来维护。在这种情况下,基于ASP.NET角色管理模块的授权模式是一个不错的选择。

目录:
一、 ASP.NET Roles提供程序
二、 ASP.NET Roles授权与认证的无关性
三、 ASP.NET Roles授权 在ServiceAuthorizationBehavior中的设定

一、ASP.NET Roles提供程序

和Membership一样,Roles也是ASP.NET一个重要的提供程序,旨在解决对角色的维护和基于角色的授权。ASP.NET Roles同样采用策略设计模式,角色的添加、删除、获取以及授权功能定义在System.Web.Security.RoleProvider这个抽象类中。而ASP.NET默认提供了如下三个具体的RoleProvider,它们同时也体现了角色和授权信息的三种不同的存储形式。如果它们还不能满足你的具体授权要求,你还可以自定义RoleProvider。比如说,如果你使用的数据库是Oracle,你可以参考SqlRoleProvider自定义一个OracleRoleProvider。

  • SqlRoleProvider:将角色和授权信息存储于SQL Server数据库预定义的表中;
  • WindowsTokenRoleProvider:直接使用Windows用户组进行授权,这是一个只读的RoleProvider,角色(用户组)的添加和删除操作是不允许的;
  • AuthorizationStoreRoleProvider:使用Authorization Manager(AzMan)库做作为角色存储。

ASP.NET Roles相关的功能基本上都可以通过调用Roles这个静态类的相应的方法来完成。下面的代码片断列出了Roles的主要方法。其中CreateRole和DeleteRole用于进行角色创建和删除;RoleExists用户确定指定的角色是否存在;而AddUser(s)ToRole(s)和RemoveUser(s)FromRole(s)则用以建立和解除用户和角色的关系。而IsUserInRole用以确定指定的用户具有相应的角色。

   1: public static class Roles
   2: {
   3:     //其他成员
   4:     public static void CreateRole(string roleName);
   5:     public static bool DeleteRole(string roleName);
   6:     public static bool DeleteRole(string roleName, bool throwOnPopulatedRole);
   7:     public static bool RoleExists(string roleName);
   8:  
   9:     public static void AddUsersToRole(string[] usernames, string roleName);
  10:     public static void AddUsersToRoles(string[] usernames, string[] roleNames);
  11:     public static void AddUserToRole(string username, string roleName);
  12:     public static void AddUserToRoles(string username, string[] roleNames);
  13:  
  14:     public static void RemoveUserFromRole(string username, string roleName);
  15:     public static void RemoveUserFromRoles(string username, string[] roleNames);
  16:     public static void RemoveUsersFromRole(string[] usernames, string roleName);
  17:     public static void RemoveUsersFromRoles(string[] usernames, string[] roleNames);
  18:  
  19:     public static bool IsUserInRole(string roleName);
  20:     public static bool IsUserInRole(string username, string roleName);
  21: }

针对Roles的方法AddUser(s)ToRole(s),有一点值得一提:这四个方法并不会进行用户账号存在与否的验证。原因很简单,用户账号的管理属于Membership的范畴,而建立用户与角色的关系才是属于角色管理需要负责的。Membership和Roles对于ASP.NET是相互独立的两个提供程序,它们不具有任何依赖关系。你完全可以采用ActiveDirectoryMembershipProvider利用AD进行用户账号管理和认证,而采用将角色维护在基于SqlRoleProvider的SQL Server数据表中。在这着情况下,当我们调用Roles的AddUser(s)ToRole(s)方法的时候,指定的用户帐号在数据库中是不存在的。所以,Roles不会进行用户存在与否的验证,它只是负责将指定的用户名添加到相应的角色之中而以。Membership和Roles的这种独立性同样体现在WCF上。

二、ASP.NET Roles授权与认证的无关性

通过前面的介绍我们很清楚地知道了Windows用户组授权依赖于Windows认证,但是如果你采用了ASP.NET Roles安全主体权限模式,你可以采用任何非匿名客户端凭证和认证方式。也就是说,ASP.NET Roles模式真正体现了认证和授权的无关性

在采用ASP.NET Roles安全主体权限模式下,最终创建并作为当前线程安全主体的是一个RoleProviderPrincipal对象。而该RoleProviderPrincipal的Identity与当前ServiceSecurityContext的PrimaryIdentity属性实际上是同一个对象。两者的统一性可以通过于如下的验证程序来体现。

   1: IIdentity identity1 = Thread.CurrentPrincipal.Identity;
   2: IIdentity identity2 = ServiceSecurityContext.Current.PrimaryIdentity;
   3: Debug.Assert(object.ReferenceEquals(identity1,identity2));

原则上,只要通过本认证的用户名能够通过ASP.NET Roles正确获取到反映权限的角色列表,授权就能顺利进行。如果采用Windows认证(包括之前提到的三种情况),你需要针对Windows帐号(域名/用户名)进行角色分配。如果采用基于Membership和Custom的用户名/密码认证,则直接针对用户名角色的分配。如果采用证书凭证并不允许Windows帐号映射,那么被认证的用户名是证书主体名称和指纹的组合(<<主题名称>>; <<指纹>>),你需要以此进行权限(角色)的设置。

三、ASP.NET Roles授权 在ServiceAuthorizationBehavior中的设定

之前已经说过了,所有基于安全主体授权的编程都体现在ServiceAuthorizationBehavior这个服务行为上。如果要让WCF采用ASP.NET Roles进行授权,我们需要将ServiceAuthorizationBehavior的PrincipalPermissionMode属性设置成PrincipalPermissionMode.UseAspNetRoles,并为其RoleProvider属性指定一个具体的RoleProvider。至于RoleProvider的获取,你可以通过Roles的Provider得到默认的RoleProvider。此外,Roles还具有一个类似于字典类型的Providers属性返回所有配置的RoleProvider列表,你可以通过传入配置名称获取相应的RoleProvider。

   1: public sealed class ServiceAuthorizationBehavior : IServiceBehavior
   2: {
   3:     //其他成员
   4:     public PrincipalPermissionMode PrincipalPermissionMode { get; set; }
   5:     public RoleProvider RoleProvider { get; set; }
   6: }
   7: public static class Roles
   8: {
   9:     //其他成员
  10:     public static RoleProvider Provider { get; }
  11:     public static RoleProviderCollection Providers { get; }
  12: }

下面给出的是一段基于自我寄宿的代码。在开启ServiceHost之前,我们为服务指定了一个ServiceAuthorizationBehavior行为,并将其安全主体权限模式设置成PrincipalPermissionMode.UseAspNetRoles,该ServiceAuthorizationBehavior使用当前配置的默认RoleProvider。

   1: using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
   2: {
   3:     host.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.UseAspNetRoles;
   4: host.Authorization.RoleProvider = Roles.Provider
   5:     host.Open();
   6:     //...
   7: }

我们还是一如既往地推荐采用配置的方式进行服务授权的设置。在下面这段配置中,我们在<system.web>/<roleManager>节点下配置了一个唯一的类型为SqlRoleProvider的RoleProvider。该SqlRoleProvider的配置名称为sqlRoleProvider,而目标数据库对应的连接字符串名称为aspNetDb。而ServiceAuthorizationBehavior配置在名称为aspNetRolesAuthorization的服务行为配置节中,反映其安全主体权限模式的principalPermissionMode属性被设置成UseAspNetRoles,而roleProviderName属性则正是配置的RoleProvider的名称。

   1: <configuration>
   2:   <connectionStrings>
   3:     <add name="aspNetDb" connectionString="..." providerName="System.Data.SqlClient"/>
   4:   </connectionStrings>
   5:   <system.web>    
   6:     <roleManager enabled="true" defaultProvider="SqlRoleProvider">
   7:       <providers>
   8:         <add name="sqlRoleProvider" 
   9: type="System.Web.Security.SqlRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" 
  10: connectionStringName="aspNetDb" applicationName="AspRolesAuthorizationDemo"/>
  11:       </providers>
  12:     </roleManager>
  13:     </system.web>
  14:   <system.serviceModel>
  15:     <services>
  16:       <service name="Artech.WcfServices.Services.CalculatorService" behaviorConfiguration="aspNetRolesAuthorization">
  17:         <endpoint address="http://127.0.0.1/calculatorservice" binding="ws2007HttpBinding" 
  18: contract="Artech.WcfServices.Contracts.ICalculator"/>
  19:       </service>
  20:     </services>
  21:     <behaviors>
  22:       <serviceBehaviors>
  23:         <behavior name="aspNetRolesAuthorization">
  24:           <serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="sqlRoleProvider"/>          
  25:         </behavior>
  26:       </serviceBehaviors>
  27:     </behaviors>
  28:   </system.serviceModel>
  29: </configuration>

为了让读者对基于ASP.ENT Roles授权方式有一个全面的认识,我们将在《下篇》做一个具体的实例演示,敬请期待。

[WCF权限控制]ASP.NET Roles授权[上篇]
[WCF权限控制]ASP.NET Roles授权[下篇]


作者:蒋金楠
微信公众账号:大内老A
微博:www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
上一篇:美国科学院院士张首晟:区块链将使互联网进入“合久必分”的时代


下一篇:SSH文件权限