为了账号安全,请及时绑定邮箱和手机立即绑定

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

标签:
资讯

为了让读者对基于ASP.ENT Roles授权方式有一个全面的认识,我们现在来做一个实例演示。在这个实例中,我们将采用不同的认证方式,包括Windows认证和证书认证(ASP.NET Membership + Roles为常见的组合方式,在这里就不多作演示)。简单起见,我们依然沿用一贯的基于如下图所示的解决方案结构,并且依然采用声明式的授权。所以在服务操作方法Add上通过应用PrincipalPermissionAttribute特性指定其被授权的角色Administrators。

   1: public class CalculatorService : ICalculator

   

   2: {

   

   3:     [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]

   

   4:     public double Add(double x, double y)

   

   5:     {

   

   6:         return x + y;

   

   7:     }

   

   8: }


一、为SqlRoleProvider创建数据库

我们具体采用的RoleProvider为SqlRoleProvider。为此,我们首先需要做的就是创建相应的数据库。ASP.NET所有提供程序(比如Membership、Roles、Profile和Site Map等)所用的数据库的初始化工作都可以通过aspnet_regsql.exe这个工具来生成。当你创建了数据库之后,你需要在aspnet_Applications表中插入一条记录,以表示我们我们即将演示的应用。你可以直接执行如下的一段SQL脚本,在该校本中我们将演示应用起名为AspRolesAuthorizationDemo

   1: INSERT INTO [aspnet_Applications]

   

   2:            ([ApplicationName]

   

   3:            ,[LoweredApplicationName]

   

   4:            ,[ApplicationId]

   

   5:            ,[Description])

   

   6: VALUES

   

   7:            (

   

   8:              'AspRolesAuthorizationDemo'

   

   9:              ,'asprolesauthorizationdemo '

   

  10:              ,NEWID()

   

  11:              ,''

   

  12:         )


二、在Windows认证下使用ASP.ENT Roles授权

我们授权演示的是在客户端凭证类型为Windows的情况下采用ASP.NET Roles授权模式,为此我们需要更新一下服务端和客户端的配置。注意不要忘了将根据你的实际情况修正连接字符串。下面是服务端配置。

   1: <?xml version="1.0"?>

   

   2: <configuration>

   

   3:   <connectionStrings>

   

   4:     <add name="aspNetDb" connectionString="..." providerName="System.Data.SqlClient"/>

   

   5:   </connectionStrings>

   

   6:   <system.web>

   

   7:     <roleManager enabled="true" defaultProvider="sqlRoleProvider">

   

   8:       <providers>

   

   9:         <add name="sqlRoleProvider"

   

  10: type="System.Web.Security.SqlRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"

   

  11: connectionStringName="AspNetDb" applicationName="AspRolesAuthorizationDemo"/>

   

  12:       </providers>

   

  13:     </roleManager>

   

  14:   </system.web>

   

  15:   <system.serviceModel>

   

  16:     <services>

   

  17:       <service name="Artech.WcfServices.Services.CalculatorService" behaviorConfiguration="useAspNetRoles">

   

  18:         <endpoint address="http://127.0.0.1/calculatorservice" binding="ws2007HttpBinding"

   

  19: contract="Artech.WcfServices.Contracts.ICalculator"/>

   

  20:       </service>

   

  21:     </services>

   

  22:     <behaviors>

   

  23:       <serviceBehaviors>

   

  24:         <behavior  name="useAspNetRoles">

   

  25:           <serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="sqlRoleProvider"/>

   

  26:         </behavior>

   

  27:       </serviceBehaviors>

   

  28:     </behaviors>

   

  29:   </system.serviceModel>

   

  30: </configuration>

下面是客户端配置。

   1: <?xml version="1.0"?>

   

   2: <configuration>

   

   3:   <system.serviceModel>

   

   4:     <client>

   

   5:       <endpoint name="calculatorService" address="http://127.0.0.1/calculatorservice" binding="ws2007HttpBinding"

   

   6: contract="Artech.WcfServices.Contracts.ICalculator"/>

   

   7:     </client>

   

   8:   </system.serviceModel>

   

   9: </configuration>

在这之前我们需要创建了两个Windows帐号Foo和Bar,密码为Password。由于我们现在是采用ASP.NET Roles进行授权,我们需要通过Roles这个静态类为他们分配相应的权限。为了省事,我直接将相应的实现写在如下所示的服务寄宿程序中。在这段代码中,如果Administrators角色不存在,先创建它,并将其分配给用户Jinnan-PC\Foo(Jinnan-PC为我的机器名,对于域帐号,用域名替换)。

   1: if (!Roles.RoleExists("Administrators"))

   

   2: {

   

   3:     Roles.CreateRole("Administrators");

   

   4: }

   

   5: if(!Roles.IsUserInRole(@"Jinnan-PC\Foo","Administrators"))

   

   6: {

   

   7:     Roles.AddUserToRole(@"Jinnan-PC\Foo","Administrators");

   

   8: }

   

   9: using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))

   

  10: {

   

  11:     host.Open();

   

  12:     Console.Read();

   

  13: }

然后客户端分别以Foo和Bar的名义进行两次服务调用,下面是客户端程序:

   1: ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorService");

   

   2: NetworkCredential credential = channelFactory.Credentials.Windows.ClientCredential;

   

   3: credential.UserName = "Foo";

   

   4: credential.Password = "Password";

   

   5: ICalculator calculator = channelFactory.CreateChannel();

   

   6: Invoke(calculator);

   

   7:

   

   8: channelFactory = new ChannelFactory<ICalculator>("calculatorService");

   

   9: credential = channelFactory.Credentials.Windows.ClientCredential;

   

  10: credential.UserName = "Bar";

   

  11: credential.Password = "Password";

   

  12: calculator = channelFactory.CreateChannel();

   

  13: Invoke(calculator);

其中Invoke方法定义如下:

   1: static void Invoke(ICalculator calculator)

   

   2: {

   

   3:     try

   

   4:     {

   

   5:         calculator.Add(1,2);

   

   6:         Console.WriteLine("服务调用成功...");

   

   7:     }

   

   8:     catch (Exception ex)

   

   9:     {

   

  10:         Console.WriteLine("服务调用失败...");

   

  11:     }

   

  12: }

由于Foo在服务启动之初就已经分配了Adminstrators角色,而Bar没有,所以只有第一次服务调用能够成功。而最终的执行结果也印证了这一点。

   1: 服务调用成功...

   

   2: 服务调用失败...


三、在X.509证书认证下使用ASP.ENT Roles授权

接下来我们来演示客户端使用X.509证书的情况下如何使用ASP.ENT Roles授权。为此我们需要通过如下的命令行创建三个主题名称(CN)分别为Jinnan-PC(你可以任意指定该证书主体名称)、Foo和Bar的证书。第一个作为服务证书,后两个坐位客户端证书。它们都自动保存到本机(LocalMachine)的个人证书存储区。然后我们利用MMC的证书管理单元将Foo和Bar两证书导入到受信任人(Trusted People)证书存储区。

   1: MakeCert –n “CN=Jinnan-PC” –sr LocalMachine –ss My –pe –sky exchange

   

   2: MakeCert –n “CN=Foo” –sr LocalMachine –ss My –pe –sky exchange

   

   3: MakeCert –n “CN=Bar” –sr LocalMachine –ss My –pe –sky exchange

为了采用X.509证书作为客户端凭证,我们需要修改服务端和客户端的配置。在服务端配置中,不仅仅通过服务行为进行基于ASP.NET Roles授权相应的设置,还为服务设置了服务证书(Jinnan-PC),以及针对证书的认证模式(PeerOrChainTrust)。而客户端则将服务证书的认证模式设为None。下面是服务端配置。

   1: <?xml version="1.0"?>

   

   2: <configuration>

   

   3:   <connectionStrings>

   

   4:     <add name="AspNetDb" connectionString="..." providerName="System.Data.SqlClient"/>

   

   5:   </connectionStrings>

   

   6:   <system.web>

   

   7:     <roleManager enabled="true" defaultProvider="SqlRoleProvider">

   

   8:       <providers>

   

   9:         <add name="sqlRoleProvider"

   

  10: type="System.Web.Security.SqlRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"

   

  11: connectionStringName="AspNetDb" applicationName="AspRolesAuthorizationDemo"/>

   

  12:       </providers>

   

  13:     </roleManager>

   

  14:     </system.web>

   

  15:   <system.serviceModel>

   

  16:     <bindings>

   

  17:       <ws2007HttpBinding>

   

  18:         <binding name="certificateCredentialBinding">

   

  19:           <security mode="Message">

   

  20:             <message clientCredentialType="Certificate"/>

   

  21:           </security>

   

  22:         </binding>

   

  23:       </ws2007HttpBinding>

   

  24:     </bindings>

   

  25:     <services>

   

  26:       <service name="Artech.WcfServices.Services.CalculatorService" behaviorConfiguration="useAspNetRoles">

   

  27:         <endpoint address="http://127.0.0.1/calculatorservice" binding="ws2007HttpBinding" bindingConfiguration="certificateCredentialBinding"

   

  28: contract="Artech.WcfServices.Contracts.ICalculator"/>

   

  29:       </service>

   

  30:     </services>

   

  31:     <behaviors>

   

  32:       <serviceBehaviors>

   

  33:         <behavior  name="useAspNetRoles">

   

  34:           <serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="sqlRoleProvider"/>

   

  35:           <serviceCredentials>

   

  36:             <serviceCertificate storeLocation="LocalMachine" storeName ="My" x509FindType="FindBySubjectName" findValue="Jinnan-PC"/>

   

  37:             <clientCertificate>

   

  38:               <authentication certificateValidationMode="PeerOrChainTrust"/>

   

  39:             </clientCertificate>

   

  40:           </serviceCredentials>

   

  41:         </behavior>

   

  42:       </serviceBehaviors>

   

  43:     </behaviors>

   

  44:   </system.serviceModel>

   

  45: </configuration>

下面是客户端配置。

   1: <?xml version="1.0"?>

   

   2: <configuration>

   

   3:   <system.serviceModel>

   

   4:     <bindings>

   

   5:       <ws2007HttpBinding>

   

   6:         <binding name="certificateCredentialBinding">

   

   7:           <security mode="Message">

   

   8:             <message clientCredentialType="Certificate"/>

   

   9:           </security>

   

  10:         </binding>

   

  11:       </ws2007HttpBinding>

   

  12:     </bindings>

   

  13:     <client>

   

  14:       <endpoint name="calculatorService" behaviorConfiguration="ignoreCertValidation"

   

  15: address="http://127.0.0.1/calculatorservice" binding="ws2007HttpBinding" bindingConfiguration="certificateCredentialBinding"

   

  16: contract="Artech.WcfServices.Contracts.ICalculator">

   

  17:         <identity>

   

  18:           <certificateReference storeLocation="LocalMachine" storeName ="My" x509FindType="FindBySubjectName" findValue="Jinnan-PC"/>

   

  19:         </identity>

   

  20:       </endpoint>

   

  21:     </client>

   

  22:     <behaviors>

   

  23:       <endpointBehaviors>

   

  24:         <behavior name="ignoreCertValidation">

   

  25:           <clientCredentials>

   

  26:             <serviceCertificate>

   

  27:               <authentication certificateValidationMode="None"/>

   

  28:             </serviceCertificate>

   

  29:           </clientCredentials>

   

  30:         </behavior>

   

  31:       </endpointBehaviors>

   

  32:     </behaviors>

   

  33:   </system.serviceModel>

   

  34: </configuration>

现在我需要做的是通过Roles这个静态类型对以证书表示的两个用户进行角色的分配。之前我们已经说过,当客户端采用证书作为客户端凭证的情况下,用户名称得格式为(<<主题名称>>; <<指纹>>)。Foo的主题名称为CN=Foo,你可以通过MMC的证书管理单元查看证书的指纹,比如指纹内容为50819320DAAF1BAD9DE8823D3216BE9B36760C4D。那么我们只需要针对用户名“CN=Foo; 50819320DAAF1BAD9DE8823D3216BE9B36760C4D”进行授权就可以了。我们一样将角色分配实现在服务寄宿程序中。

   1: if (!Roles.RoleExists("Administrators"))

   

   2: {

   

   3:     Roles.CreateRole("Administrators");

   

   4: }

   

   5: if (!Roles.IsUserInRole("CN=Foo; 50819320DAAF1BAD9DE8823D3216BE9B36760C4D", "Administrators"))

   

   6: {

   

   7:     Roles.AddUserToRole("CN=Foo; 50819320DAAF1BAD9DE8823D3216BE9B36760C4D", "Administrators");

   

   8: }

   

   9: using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))

   

  10: {

   

  11:     host.Open();

   

  12:     Console.Read();

   

  13: }

然后客户端分别使用针对Foo和Bar两张不同证书作为凭证进行服务调用,相应的客户端程序如下所示。根据权限的不同,也只有第一次服务调用能够成功。

客户端程序:

   1: ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorService");

   

   2: channelFactory.Credentials.ClientCertificate.SetCertificate( StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName,"Foo");

   

   3: ICalculator calculator = channelFactory.CreateChannel();

   

   4: Invoke(calculator);

   

   5:

   

   6: channelFactory = new ChannelFactory<ICalculator>("calculatorService");

   

   7: channelFactory.Credentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, "Bar");

   

   8: calculator = channelFactory.CreateChannel();

   

   9: Invoke(calculator);

输出结果:

   1: 服务调用成功...

   

   2: 服务调用失败...

 


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消