[WCF权限控制]利用WCF自定义授权模式提供当前Principal[原理篇]

在《通过扩展自行实现服务授权》一文中,我通过自定义CallContextInitializer的方式在操作方法之前之前根据认证用户设置了当前线程的安全主体,从而实现授权的目的。实际上,WCF的安全体系本就提供相应的扩展,使你能够自由地实现安全主体的提供方式。具体来说,安全主体的提供可以通过自定AuthorizationPolicy或者ServiceAuthorizationManager来实现。

一、AuthorizationPolicy

在WCF安全应用编程接口中,所有的AuthorizationPolicy实现了IAuthorizationPolicy接口。如下面的代码所示,IAuthorizationPolicy继承自IAuthorizationComponent接口,本身具有一个ClaimSet类型的Issuer属性和一个Evaluate方法。关于ClaimSet,我们会在后续的部分继续介绍,这里我们只需要关注Evaluate方法。该方法的第一个参数的类型为System.IdentityModel.Policy.EvaluationContext,它具有一个字典类型的只读属性Properties。

   1: public interface IAuthorizationPolicy : IAuthorizationComponent
   2: {
   3:     bool Evaluate(EvaluationContext evaluationContext, ref object state);
   4:     ClaimSet Issuer { get; }
   5: }
   6: public abstract class EvaluationContext
   7: {
   8:     //其他成员
   9:     public abstract IDictionary<string, object> Properties { get; }
  10: }

如果我们需要通过自定义的方式来提供安全主体,我们只需要通过实现IAuthorizationPolicy接口创建自定义的AuthorizationPolicy,并在Evaluate方法中将创建安全主体对象添加到EvaluationContext的Properties字典中即可。在该字典中,用于存放安全主体条目对应的键值为“Principal”。

   1: Public class CustomAuthorizationPolicy:IAuthorizationPolicy
   2: {
   3:    //其他成员
   4:    bool Evaluate(EvaluationContext evaluationContext, ref object state)
   5:    {
   6:      //其他操作
   7:       evaluationContext. Properties[“Principal”] = customPrincipal;
   8:       return true;
   9:    }
  10: }

那么自定义的AuthorizationPolicy通过怎样的方式被应用到WCF的授权运行时呢?这还是要借助于我们已经很熟悉的服务行为ServiceAuthorizationBehavior。如下面给出的代码片断所示,ServiceAuthorizationBehavior具有一个类型为ReadOnlyCollection<IAuthorizationPolicy>
的ExternalAuthorizationPolicies属性,表示自定义AuthorizationPolicy的集合。

   1: public sealed class ServiceAuthorizationBehavior : IServiceBehavior
   2: {
   3:     //其他成员
   4:     public ReadOnlyCollection<IAuthorizationPolicy> ExternalAuthorizationPolicies { get; set; }
   5: }

你可以通过编程的方式将自定义的AuthorizationPolicy添加到ServiceAuthorizationBehavior的ExternalAuthorizationPolicies集合中,也可以通过配置指定自定义AuthorizationPolicy的类型。如下面给出的配置片断所示,ServiceAuthorizationBehavior的ExternalAuthorizationPolicies集合对应的配置节点为<serviceAuthorization>/<authorizationPolicies>。

   1: <configuration>
   2:   <system.serviceModel>
   3:     <behaviors>
   4:       <serviceBehaviors>
   5:         <behavior  name="useCustomAuthorization">         
   6:           <serviceAuthorization principalPermissionMode="Custom">
   7:             <authorizationPolicies >
   8:               <add policyType="AuthorizationPolicyType1" />
   9:               <add policyType="AuthorizationPolicyType2" />
  10:               ...
  11:             </authorizationPolicies>
  12:           </serviceAuthorization>
  13:           <serviceDebug includeExceptionDetailInFaults="true"/>
  14:         </behavior>
  15:       </serviceBehaviors>
  16:     </behaviors>
  17:   </system.serviceModel>
  18: </configuration>

二、ServiceAuthorizationManager

在ServiceAuthorizationBehavior选择Custom安全主体权限模式的情况下,除了自定义AuthorizationPolicy,你还可以通过自定义ServiceAuthorizationManager来提供当前的安全主体。下面给出了ServiceAuthorizationManager的定义,从中我们可以看出它具有两个CheckAccess方法用于实现授权。方法的返回值表示当前请求的服务操作是否被授权指定。实际上最终的授权判断实现在受保护方法CheckAccessCore中,并且在ServiceAuthorizationManager中该方法直接返回True。

   1: public class ServiceAuthorizationManager
   2: {
   3:     //其他成员
   4:     public virtual bool CheckAccess(OperationContext operationContext);
   5:     public virtual bool CheckAccess(OperationContext operationContext, ref Message message);
   6:     protected virtual bool CheckAccessCore(OperationContext operationContext);
   7: }

当ServiceAuthorizationBehavior的PrincipalPermissionMode被设置成Custom的情况下,被设置的当前安全主体实际上是通过当前服务安全上下文(ServiceSecurityContext)获取的。具体来说,ServiceSecurityContext具有一个表示授权信息的AuthorizationContext对象。和EvaluationContext一样,AuthorizationContext也具有一个字典类型的Properties属性。实际上,通过AuthorizationPolicy添加到EvaluationContext中的属性,最终都会被转移到当前AuthorizationContext的Properties属性中。

   1: public class ServiceSecurityContext
   2: {
   3:     //其他成员
   4:     public AuthorizationContext AuthorizationContext { get; }
   5: }
   6: public abstract class AuthorizationContext : IAuthorizationComponent
   7: {  
   8:     //其他成员
   9:     public abstract IDictionary<string, object> Properties { get; }
  10: }

所以只要我们能够在WCF从当前AuthorizationContext获取安全主体之前对其进行初始化,整个基于安全主体的授权体系就能正常运作,而这个工作可以通过自定义ServiceAuthorizationManager来实现。一般来讲,我们只需通过继承ServiceAuthorizationManager,重写虚方法CheckAccessCore进行安全主体的初始化。

   1: public class CustomServiceAuthorizationManager : ServiceAuthorizationManager
   2: {
   3:     protected override bool CheckAccessCore(OperationContext operationContext)
   4: {
   5:     //其他操作
   6:         AuthorizationContext authorizationContext = operationContext.ServiceSecurityContext.AuthorizationContext;
   7:         authorizationContext.Properties["Principal"] = customPrincipal;
   8:         return true;
   9:     }
  10: }

自定义的ServiceAuthorizationManager最终还是通过ServiceAuthorizationBehavior这个服务行为应用到WCF授权框架体系中。如下面给出的代码片断所示,在ServiceAuthorizationBehavior中依然具有相应属性定义的。而在ServiceAuthorizationBehavior的配置节中,ServiceAuthorizationManager对应的配置属性为serviceAuthorizationManager,你可以通过该配置属性将设置自定义ServiceAuthorizationManager的类型。

   1: public sealed class ServiceAuthorizationBehavior: IServiceBehavior
   2: {
   3:     //其他成员
   4:     public ServiceAuthorizationManager ServiceAuthorizationManager { get; set; }
   5: }

如果两种默认的安全主体权限模式(UseWindowsGroup和UseAspNetRoles)不能满足你的要求,你需要自定义安全主体提供方式,自定义AuthorizationPolicy或者ServiceAuthorizationManager不失为一个很好的解决方案。为了让你对此有个深刻的认识,在《下篇》中我们提供一个完整的实例。

[WCF权限控制]利用WCF自定义授权模式提供当前安全主体[原理篇]

[WCF权限控制]利用WCF自定义授权模式提供当前安全主体[实例篇]

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

原文链接

时间: 2024-11-02 23:06:57

[WCF权限控制]利用WCF自定义授权模式提供当前Principal[原理篇]的相关文章

[WCF权限控制]利用WCF自定义授权模式提供当前Principal[实例篇]

在<原理篇>中我们谈到:如果采用自定义安全主体权限模式,我们可以通过自定义AuthorizationPolicy或者ServiceAuthorizationManager实现对基于当前认证用于相关的安全主体的提供,进而达到授权的目的.为了让大家对此有个更加深刻的认识,在这篇文章中我们会提供一个具体的例子.[源代码从这里下载] 目录: 一.创建自定义AuthorizationPolicy 二.创建自定义ServiceAuthorizationManager 三.通过自定义Authorizatio

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

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

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

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

[WCF权限控制]WCF自定义授权体系详解[实例篇]

在<原理篇>中,我们谈到WCF自定义授权体系具有两个核心的组件:AuthorizationPolicy和ServiceAuthorizationManager,已经它们是如何写作最终提供一种基于声明的授权实现.为了让自定义授权有深刻的理解,我们来进行一个简单实例来演示如何通过自定义这两个组件实现"非角色授权策略".[源代码从这里下载] 目录: 一.创建演示程序解决方案 二.自定义AuthorizationPolicy 三.自定义ServiceAuthorizationMan

[WCF权限控制]基于Windows用户组的授权方式[上篇]

Windows用户组安全主体权限模式,顾名思义,就是将利用Windows安全系统将对应的Windows帐号所在的用户组作为该用户权限集的授权方式.认证和授权密不可分,但是对于认证和授权在WCF安全体系中的实现来说,它们则是相对独立的.认证属于安全传输的范畴,是在信道层实现的,而授权则是在服务模型层实现的.但是对于基于Windows用户组的授权来说,最终体现出来的授权行为却和采用何种认证具有密切的关系. 一.Windows用户组授权与认证的关系 无论是对于基于Windows用户组还是基于ASP.N

[WCF权限控制]基于Windows用户组的授权方式[下篇]

为了让读者对基于Windows用户组的授权具有深刻的认识,接下来我们通过一个简单的事例来讲解在真正的应用中该授权模式如何使用.对于接下来演示的事例,我们将采用Windows认证和授权.至于授权的最终实现,我们采用的是在服务方法上面应用PrincipalPermissionAttribute特性方式的声明式授权.[源代码从这里下载] 目录: 步骤一.创建测试帐号 步骤二.创建服务契约和服务 步骤三.寄宿服务 步骤四.创建客户端程序 步骤一.创建测试帐号 在创建事例解决方案之前我们先完成相应的准备工

[WCF权限控制]WCF的三种授权模式

前面的两篇文章(<从两个重要的概念谈起:Identity与Principal[上篇]>和<从两个重要的概念谈起:Identity与Principal[下篇]>)主要探讨基于安全主体的授权.通过这些介绍我们知道:如果我们在实施授权的时候,当前线程的安全主体能够被正确设置,我们就可以正确地完成授权.基于相同的原理,对于WCF的服务授权,如果正确的安全主体能够在服务操作被执行之前被正确设置到当前线程,借助于这个安全主体,我们不但可以采用命令式编程的方式将授权逻辑写在相应的操作中,也可以采

[WCF权限控制]WCF自定义授权体系详解[原理篇]

到目前为止,我么介绍的授权策略都是围绕着安全主体进行的,基本上都是基于角色的授权.虽然角色是定义权限最为常用的形式,但是它解决不了授权的所有问题.基于角色的授权策略一般是这样的:需要进行访问控制的操作或者资源关联到某个角色上,那么只要访问者被分配了该角色,就被授予了相应的权限.那么假设我们的授权策略是这样的:访问权限和两个角色进行关联,访问者需要同时被分配了这两个角色才能被授权.这是一个很常见的授权策略,但是典型的基于单一角色的授权解决不了这个问题(除非为两个角色的交集创建新的角色).而这仅仅是

[WCF权限控制]模拟(Impersonation)与委托(Delegation)[上篇]

由于服务操作是在寄宿进程中执行,在默认的情况下,服务操作是否具有足够的权限访问某个资源(比如文件)决定于执行寄宿进程Windows帐号的权限设置,而与作为客户端的Windows帐号无关.在有多情况下,我们希望服务操作执行在基于客户端的安全上下文中执行,以解决执行服务进行的帐号权限不足的问题.这就涉及到一个重要的话题--模拟(Impersonation)与委托(Delegation)[实例程序源代码从这里下载] 目录: 一.从访问令牌(Access Token)说起 二.再谈WindowsIden