[WCF權(quán)限控制]WCF自定義授權(quán)體系詳解[原理篇]
到目前為止,我么介紹的授權(quán)策略都是圍繞著安全主體進(jìn)行的,基本上都是基于角色的授權(quán)。雖然角色是定義權(quán)限最為常用的形式,但是它解決不了授權(quán)的所有問題。基于角色的授權(quán)策略一般是這樣的:需要進(jìn)行訪問控制的操作或者資源關(guān)聯(lián)到某個角色上,那么只要訪問者被分配了該角色,就被授予了相應(yīng)的權(quán)限。那么假設(shè)我們的授權(quán)策略是這樣的:訪問權(quán)限和兩個角色進(jìn)行關(guān)聯(lián),訪問者需要同時被分配了這兩個角色才能被授權(quán)。這是一個很常見的授權(quán)策略,但是典型的基于單一角色的授權(quán)解決不了這個問題(除非為兩個角色的交集創(chuàng)建新的角色)。而這僅僅是一種簡單的授權(quán)策略,有時候授權(quán)需要通過一個復(fù)雜的表達(dá)式來表示,而且其中會涉及諸多元素,比如身份、角色和組織等。
我之所以說這么多,主要是為說明一個問題:授權(quán)策略有時候需要手工定制。而作為一種基于可擴展性的通信框架,WCF在授權(quán)方面提供了擴展點,使你可以根據(jù)的你實際需要定制相應(yīng)的授權(quán)策略。WCF為了創(chuàng)建了一個基于“聲明”的授權(quán)系統(tǒng),為了讓讀者對該系統(tǒng)的內(nèi)部原理有全面的了解,我們不妨先來討論一下這里指的聲明是如何定義的。
目錄:
一、Claim和ClaimSet
二、DispatchRuntime中的AuthorizationPolicy和ServiceAuthorizationManager
三、通過自定義AuthorizationPolicy創(chuàng)建基于自定義授權(quán)策略的聲明
四、通過自定義ServiceAuthorizationManager根據(jù)聲明作出最后的授權(quán)判斷
一、Claim和ClaimSet
聲明描述了與系統(tǒng)中某個實體關(guān)聯(lián)的功能,該實體通常為該系統(tǒng)中的某個用戶。通過對訪問給定的受保護(hù)資源所需的聲明和與試圖進(jìn)行訪問的實體關(guān)聯(lián)的聲明進(jìn)行比較,便可確定該資源的訪問權(quán)限。聲明是針對特定值的權(quán)限表達(dá)式。權(quán)限可以是讀取、寫入或擁有。值可以是數(shù)據(jù)庫、文件、郵箱或?qū)傩浴B暶鬟€具有聲明類型。聲明類型和權(quán)限的組合提供了用于針對該值指定的功能的機制。在WCF安全應(yīng)用編程接口中,生命通過類型Claim表示。從下面給出的關(guān)于Claim定義的代碼片斷中,我們可以認(rèn)識到:一個通過Claim對象表示的聲明具有如下三要素:聲明類型(ClaimType)、聲明關(guān)聯(lián)的資源(Resource)和聲明代表的權(quán)限類型(Right)。
1: public class Claim
2: {
3: //其他成員
4: public string ClaimType { get; }
5: public object Resource { get; }
6: public string Right { get; }
7: }
通過Right屬性表示的權(quán)限類型一般通過一個統(tǒng)一資源標(biāo)識符(URI)來表示,而靜態(tài)類Rights定義了兩個預(yù)定義的權(quán)限類型:Identity和PossessProperty。前者表示聲明用于身份標(biāo)識,后者則表示聲明關(guān)聯(lián)的實體具有的屬性。Rights類定義如下。
1: public static class Rights
2: {
3: public static string Identity { get; }
4: public static string PossessProperty { get; }
5: }
二、DispatchRuntime中的AuthorizationPolicy和ServiceAuthorizationManager
在上面我們已經(jīng)提到過了,借助于WCF的擴展,我們通過自定義AuthorizationPolicy和ServiceAuthorizationManager來讓W(xué)CF按照我們自定義的授權(quán)策略進(jìn)行訪問控制。那么。這兩個對象是如何參與到WCF的授權(quán)執(zhí)行流程中的呢?
我們首先需要了解的是:自定義的AuthorizationPolicy和ServiceAuthorizationManager通過服務(wù)行為ServiceAuthorizationBehavior成為WCF運行時的一部分。具體來說,在ServiceAuthorizationBehavior的ApplyDispatchBehavior方法被調(diào)用的時候,定義在ExternalAuthorizationPolicies屬性中的AuthorizationPolicy列表和ServiceAuthorizationManager被賦值給所有終結(jié)點的分發(fā)運行時。在DispatchRuntime類型中,具有兩個同名的屬性。
1: public sealed class DispatchRuntime
2: {
3: //其他成員
4: public ReadOnlyCollection<IAuthorizationPolicy> ExternalAuthorizationPolicies { get; set; }
5: public ServiceAuthorizationManager ServiceAuthorizationManager { get; set; }
6: }
三、通過自定義AuthorizationPolicy創(chuàng)建基于自定義授權(quán)策略的聲明
整個自定義授權(quán)先從AuthorizationPolicy開始。具體來說,WCF先創(chuàng)建一個EvaluationContext對象。我們之前只提到過EvaluationContext用于表示屬性的Properties,實際上它的核心是通過ClaimSets屬性表示的聲明集(ClaimSet)的集合。下面給出的EvaluationContext的整個公用成員的定義,除了Properties和ClaimSets之前,EvaluationContext還具有一個額外的屬性Generation表示聲明集被添加到ClaimSets集合的次數(shù)。而聲明集的添加通過方法AddClaimSet實現(xiàn)。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是一個抽象類型,實際被創(chuàng)建的是一個被稱為System.IdentityModel.Policy.DefaultEvaluationContext的內(nèi)部類型的對象。當(dāng)EvaluationContext被初始化之后,WCF會遍歷定義在當(dāng)前DispatchRuntime的ExternalAuthorizationPolicies屬性中的所有AuthorizationPolicy。然后依次調(diào)用它們的Evaluate方法,而傳入的參數(shù)就是之前初始化的這個EvaluationContext對象。一般地,我們通過自定義AuthorizationPolicy的目的在于通過在實現(xiàn)的Evaluate方法中將基于你自定義授權(quán)策略相關(guān)的聲明集添加到EvaluationContext的ClaimSets中。
四、通過自定義ServiceAuthorizationManager根據(jù)聲明作出最后的授權(quán)判斷
在所有的自定義AuthorizationPolicy的Evaluate方法被調(diào)用之后,最終的EvaluationContext對象被用以初始化當(dāng)前的授權(quán)上下文(AuthorizationContext)。下面給出了AuthorizationContext的所有公共屬性的定義。一般來說,除了Id,其余三個屬性直接來源于EvaluationContext。具體來說,EvaluationContext的ClaimSets和Properties作為AuthorizationContext的ClaimSets和Properties,而EvaluationContext通過RecordExpirationTime記錄的過期時間反應(yīng)在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也是一個抽象類,默認(rèn)被創(chuàng)建的是一個名稱為System.IdentityModel.Policy.DefaultAuthorizationContext的內(nèi)部類型對象。而通過EvaluationContext創(chuàng)建的AuthorizationContext最終服務(wù)于自定義的ServiceAuthorizationManager以實現(xiàn)最終授權(quán)的判斷。具體來說,WCF通過調(diào)用ServiceAuthorizationManager的CheckAccess方法決定當(dāng)前操作是否被授權(quán)訪問。
為了讓自定義授權(quán)有深刻的理解,在《實例篇》中我們將演示一個簡單的實例為你展示如何通過自定義AuthorizationPolicy和ServiceAuthorizationManager實現(xiàn)非角色授權(quán),敬請期待。
[WCF權(quán)限控制]WCF自定義授權(quán)體系詳解[原理篇]
[WCF權(quán)限控制]WCF自定義授權(quán)體系詳解[實例篇]


到目前為止,我么介紹的授權(quán)策略都是圍繞著安全主體進(jìn)行的,基本上都是基于角色的授權(quán)。雖然角色是定義權(quán)限最為常用的形式,但是它解決不了授權(quán)的所有問題。有時候授權(quán)需要通過一個復(fù)雜的表達(dá)式來表示,而且其中會涉及諸多元素,比如身份、角色和組織等。一句話,如果簡單的基于角色的授權(quán)不能解決我們的問題,我們需要自定義授權(quán)策略。
浙公網(wǎng)安備 33010602011771號