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

简介:

到目前为止,我么介绍的授权策略都是围绕着安全主体进行的,基本上都是基于角色的授权。虽然角色是定义权限最为常用的形式,但是它解决不了授权的所有问题。基于角色的授权策略一般是这样的:需要进行访问控制的操作或者资源关联到某个角色上,那么只要访问者被分配了该角色,就被授予了相应的权限。那么假设我们的授权策略是这样的:访问权限和两个角色进行关联,访问者需要同时被分配了这两个角色才能被授权。这是一个很常见的授权策略,但是典型的基于单一角色的授权解决不了这个问题(除非为两个角色的交集创建新的角色)。而这仅仅是一种简单的授权策略,有时候授权需要通过一个复杂的表达式来表示,而且其中会涉及诸多元素,比如身份、角色和组织等。

我之所以说这么多,主要是为说明一个问题:授权策略有时候需要手工定制。而作为一种基于可扩展性的通信框架,WCF在授权方面提供了扩展点,使你可以根据的你实际需要定制相应的授权策略。WCF为了创建了一个基于“声明”的授权系统,为了让读者对该系统的内部原理有全面的了解,我们不妨先来讨论一下这里指的声明是如何定义的。

目录:
一、Claim和ClaimSet
二、DispatchRuntime中的AuthorizationPolicy和ServiceAuthorizationManager
三、通过自定义AuthorizationPolicy创建基于自定义授权策略的声明
四、通过自定义ServiceAuthorizationManager根据声明作出最后的授权判断

一、Claim和ClaimSet

声明描述了与系统中某个实体关联的功能,该实体通常为该系统中的某个用户。通过对访问给定的受保护资源所需的声明和与试图进行访问的实体关联的声明进行比较,便可确定该资源的访问权限。声明是针对特定值的权限表达式。权限可以是读取、写入或拥有。值可以是数据库、文件、邮箱或属性。声明还具有声明类型。声明类型和权限的组合提供了用于针对该值指定的功能的机制。在WCF安全应用编程接口中,生命通过类型Claim表示。从下面给出的关于Claim定义的代码片断中,我们可以认识到:一个通过Claim对象表示的声明具有如下三要素:声明类型(ClaimType)声明关联的资源(Resource)声明代表的权限类型(Right)

   1: public class Claim
   2: {
   3:     //其他成员
   4:     public string ClaimType { get; }
   5:     public object Resource { get; }
   6:     public string Right { get; }
   7: }

通过Right属性表示的权限类型一般通过一个统一资源标识符(URI)来表示,而静态类Rights定义了两个预定义的权限类型:Identity和PossessProperty。前者表示声明用于身份标识,后者则表示声明关联的实体具有的属性。Rights类定义如下。

   1: public static class Rights
   2: {
   3:     public static string Identity { get; }
   4:     public static string PossessProperty { get; }
   5: }

二、DispatchRuntime中的AuthorizationPolicy和ServiceAuthorizationManager

在上面我们已经提到过了,借助于WCF的扩展,我们通过自定义AuthorizationPolicy和ServiceAuthorizationManager来让WCF按照我们自定义的授权策略进行访问控制。那么。这两个对象是如何参与到WCF的授权执行流程中的呢?

我们首先需要了解的是:自定义的AuthorizationPolicy和ServiceAuthorizationManager通过服务行为ServiceAuthorizationBehavior成为WCF运行时的一部分。具体来说,在ServiceAuthorizationBehavior的ApplyDispatchBehavior方法被调用的时候,定义在ExternalAuthorizationPolicies属性中的AuthorizationPolicy列表和ServiceAuthorizationManager被赋值给所有终结点的分发运行时。在DispatchRuntime类型中,具有两个同名的属性。

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

三、通过自定义AuthorizationPolicy创建基于自定义授权策略的声明

整个自定义授权先从AuthorizationPolicy开始。具体来说,WCF先创建一个EvaluationContext对象。我们之前只提到过EvaluationContext用于表示属性的Properties,实际上它的核心是通过ClaimSets属性表示的声明集(ClaimSet)的集合。下面给出的EvaluationContext的整个公用成员的定义,除了Properties和ClaimSets之前,EvaluationContext还具有一个额外的属性Generation表示声明集被添加到ClaimSets集合的次数。而声明集的添加通过方法AddClaimSet实现。EvaluationContext具有一个有效性,而失效的时间可以通过方法RecordExpirationTime来记录。

   1: public abstract class EvaluationContext
   2: {
   3:     public abstract void AddClaimSet(IAuthorizationPolicy policy, ClaimSet claimSet);
   4:     public abstract void RecordExpirationTime(DateTime expirationTime);
   5:  
   6:     public abstract ReadOnlyCollection<ClaimSet> ClaimSets { get; }
   7:     public abstract int Generation { get; }
   8:     public abstract IDictionary<string, object> Properties { get; }
   9: }

EvaluationContext是一个抽象类型,实际被创建的是一个被称为System.IdentityModel.Policy.DefaultEvaluationContext的内部类型的对象。当EvaluationContext被初始化之后,WCF会遍历定义在当前DispatchRuntime的ExternalAuthorizationPolicies属性中的所有AuthorizationPolicy。然后依次调用它们的Evaluate方法,而传入的参数就是之前初始化的这个EvaluationContext对象。一般地,我们通过自定义AuthorizationPolicy的目的在于通过在实现的Evaluate方法中将基于你自定义授权策略相关的声明集添加到EvaluationContext的ClaimSets中。

四、通过自定义ServiceAuthorizationManager根据声明作出最后的授权判断

在所有的自定义AuthorizationPolicy的Evaluate方法被调用之后,最终的EvaluationContext对象被用以初始化当前的授权上下文(AuthorizationContext)。下面给出了AuthorizationContext的所有公共属性的定义。一般来说,除了Id,其余三个属性直接来源于EvaluationContext。具体来说,EvaluationContext的ClaimSets和Properties作为AuthorizationContext的ClaimSets和Properties,而EvaluationContext通过RecordExpirationTime记录的过期时间反应在AuthorizationContext的ExpirationTime上。

   1: public abstract class AuthorizationContext : IAuthorizationComponent
   2: {
   3:     public abstract string Id { get; }
   4:  
   5:     public abstract ReadOnlyCollection<ClaimSet> ClaimSets { get; }
   6:     public abstract DateTime ExpirationTime { get; }
   7:     public abstract IDictionary<string, object> Properties { get; }
   8: }

和EvaluationContext一样,AuthorizationContext也是一个抽象类,默认被创建的是一个名称为System.IdentityModel.Policy.DefaultAuthorizationContext的内部类型对象。而通过EvaluationContext创建的AuthorizationContext最终服务于自定义的ServiceAuthorizationManager以实现最终授权的判断。具体来说,WCF通过调用ServiceAuthorizationManager的CheckAccess方法决定当前操作是否被授权访问。

为了让自定义授权有深刻的理解,在《实例篇》中我们将演示一个简单的实例为你展示如何通过自定义AuthorizationPolicy和ServiceAuthorizationManager实现非角色授权,敬请期待。

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


作者:蒋金楠
微信公众账号:大内老A
微博: www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号 蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
相关文章
|
安全 数据安全/隐私保护 Windows
跟着Artech学习WCF扩展(2) 自定义Channel与执行的顺序
源代码下载地址:点我 原文地址:http://www.cnblogs.com/artech/archive/2008/07/09/1238626.html 这节不看源码 看着真费劲哈   服务器端是这样的顺序 MyBindingElement.
692 0
|
XML 网络架构 数据格式
跟着Artech学习WCF(5) Responsive Service 与自定义Soap Message Header
记得以前看.NET各类框架教程在介绍SOAP时经常提到Soap Header 以前一直认为这个玩意就是个理论 应该和具体的编码和应用无关 后来在看到一些关于SOAP安全的书可以在header里 进行加密解密信息的存储 用于安全方面的验证 但一直苦于这个玩意到底是神马东西,一直没见过代码,今天A...
683 0
|
10月前
|
前端开发
WCF更新服务引用报错的原因之一
WCF更新服务引用报错的原因之一
|
9月前
|
C# 数据安全/隐私保护
c#如何创建WCF服务到发布(SqlServer版已经验证)
c#如何创建WCF服务到发布(SqlServer版已经验证)
38 0
|
9月前
|
安全 数据库连接 数据库
WCF服务创建到发布(SqlServer版)
在本示例开始之前,让我们先来了解一下什么是wcf? wcf有哪些特点? wcf是一个面向服务编程的综合分层架构。该架构的项层为服务模型层。 使用户用最少的时间和精力建立自己的软件产品和外界通信的模型。它使得开发者能够建立一个跨平台的安全、可信赖、事务性的解决方案。且能与已有系统兼容写作。 简单概括就是:一组数据通信的应用程序开发接口。
62 0
|
10月前
Visual Studio 2022 创建 WCF服务 找不到
Visual Studio 2022 创建 WCF服务 找不到
|
C++
WCF基础教程(二)——解析iis8和iis8.5+VS2013发布wcf服务问题
WCF基础教程(二)——解析iis8和iis8.5+VS2013发布wcf服务问题
102 0
WCF基础教程(二)——解析iis8和iis8.5+VS2013发布wcf服务问题