| |||||||||
日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
---|---|---|---|---|---|---|---|---|---|
27 | 28 | 29 | 30 | 31 | 1 | 2 | |||
3 | 4 | 5 | 6 | 7 | 8 | 9 | |||
10 | 11 | 12 | 13 | 14 | 15 | 16 | |||
17 | 18 | 19 | 20 | 21 | 22 | 23 | |||
24 | 25 | 26 | 27 | 28 | 29 | 30 | |||
1 | 2 | 3 | 4 | 5 | 6 | 7 |
private volatile long mask = 0xF; @Override public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) { if (!isStarted()) { return FilterReply.NEUTRAL; } // for performance reasons, skip change detection (MASK-1) times out of MASK. // Only once every MASK calls is change detection code executed // Note that MASK is a variable itself. if (((invocationCounter++) & mask) != mask) { return FilterReply.NEUTRAL; } long now = System.currentTimeMillis(); synchronized (configurationWatchList) { updateMaskIfNecessary(now); if (changeDetected(now)) { // Even though reconfiguration involves resetting the loggerContext, // which clears the list of turbo filters including this instance, it is // still possible for this instance to be subsequently invoked by another // thread if it was already executing when the context was reset. disableSubsequentReconfiguration(); detachReconfigurationToNewThread(); } } return FilterReply.NEUTRAL; }
這行 if (((invocationCounter++) & mask) != mask) {
mask = 0xf,其實(shí)要每循環(huán) 0xf 次,也就是 15 次,才會(huì)去 check 一次是否要更新,也就是說,不管過了多久,如果沒到這 15 次,也不會(huì)去檢查是否更新配置。
也就是說,我多打幾次 log,配置文件就生效了。
spring security(下簡寫為 ss)控制的安全主要有兩方面,Web 和 Method Call,這兩個(gè)方面的權(quán)限控制有比較多的相通的設(shè)計(jì),也有一些特別的功能。比如 Method Call 可以做 After Invocation 控制,而 Web 可以做 Ip 地址控制。
這里面有兩個(gè)最基本的概念:authentication manager 和 access decision manager,前者控制認(rèn)證,后都控制鑒權(quán)。
1. 在 ss 的認(rèn)證系統(tǒng)中,默認(rèn)的實(shí)現(xiàn)幫助我們提供了三個(gè)概念,用戶(user),角色(authority,一般存 role)和組(group),三者的關(guān)系是,組、角色與用戶都是多對多關(guān)系,組和角色間沒關(guān)系,默認(rèn)是不啟用組的。后續(xù),在 Acl 權(quán)限管理中,可以看到角色之間,是可以有包含(樹形?)關(guān)系的。
2. 在 ss 的鑒權(quán)系統(tǒng)中,明顯會(huì)比認(rèn)證復(fù)雜得多。有 AccessDecisionManager, AccessDecisionVoter(前置), AfterInvocationProvider(后置), RoleHierarchy, SidRetrievalStrategy, LookupStrategy, PermissionGrantingStrategy, SecurityExpressionHandler, AclService, MutableAclService, AclCache 概念過多了,要一個(gè)一個(gè)解釋
a) 中心是 AccessDecisionManager,主要負(fù)責(zé) AccessDecisionVoter 的管理,默認(rèn)提供了3種實(shí)現(xiàn):1. AffirmativeBased 如果有任何一個(gè)投票器允許訪問,請求將被立刻允許,而不管之前可能有的拒絕決定。2. ConsensusBased 多數(shù)票(允許或拒絕)決定了結(jié)果,平局的投票 和空票(全是棄權(quán)的)的結(jié)果是可配置的。3. UnanimousBased 所有的投票器必須全是允許的,否則訪問將 被拒絕。
AccessDecisionManager 在用于 Web 和 Method Call 兩種情況下,可能是不一致的,因?yàn)楣δ芤膊灰恢隆?br />
b) Method Call 除了使用 AccessDecisionManager 進(jìn)行權(quán)限判斷外,還可以增加 AfterInvocationProvider 來進(jìn)行出口數(shù)據(jù)的判斷,默認(rèn)提供了 3 種。
1) PostInvocationAdviceProvider: 需要提供一個(gè) PostInvocationAuthorizationAdvice,默認(rèn)實(shí)現(xiàn)只有一個(gè),就是 ExpressionBasedPostInvocationAdvice,可以通過 spel 來進(jìn)行權(quán)限判斷。注意 ExpressionBasedPostInvocationAdvice 中需要提供一個(gè) MethodSecurityExpressionHandler,能夠創(chuàng)建出一個(gè) MethodSecurityExpressionOperations,放到 spel context 中,供 spel function 調(diào)用,這樣的方式,在后續(xù)很常見。
2) AclEntryAfterInvocationProvider 和 AclEntryAfterInvocationCollectionFilteringProvider : 這兩種都差不多,主要依賴 AclService, ObjectIdentityRetrievalStrategy, SidRetrievalStrategy 來配合,檢查返回值的權(quán)限。Collection 版本的,可以把無權(quán)限的數(shù)據(jù)去掉,只留下有權(quán)限的數(shù)據(jù)。
c) RoleHierarchy 提供了角色之間的關(guān)系,提供了兩個(gè)實(shí)現(xiàn),一個(gè)是沒關(guān)系的,直接把 user 的 role 返回,另外一個(gè)是有繼承關(guān)系的。繼承關(guān)系實(shí)現(xiàn)挺有意思的,能夠處理多級的 include 關(guān)系,比較好用。
RoleHierarchy 的使用比較復(fù)雜,會(huì)被 AccessDecisionVoter, SidRetrievalStrategy, SecurityExpressionHandler 用到,SecurityExpressionHandler 又會(huì)被 AccessDecisionVoter 用到,所以還是有點(diǎn)兒混亂。
具體的說 SecurityExpressionHandler 會(huì)用到 PermissionEvaluator 和 RoleHierarchy,PermissionEvaluator 的一個(gè)實(shí)現(xiàn) AclPermissionEvaluator 會(huì)用到 SidRetrievalStrategy。
d) SidRetrievalStrategy 和 RoleHierarchy 的功能比較接近,比 RoleHierarchy 高一個(gè)抽象層次,功能上也有所區(qū)別,是從一個(gè) authentication 拿到所有相關(guān)的 Sid(包括 Role(GrantedAuthoritySid) 和 User(PrincipalSid)),而 RoleHierarchy 只包括了 Role(GrantedAuthoritySid)的繼承關(guān)系。
e) LookupStrategy 通過 ObjectIdentity 和 Sid 把相關(guān)的 Acl 查詢出來。可以在 LookupStrategy 擴(kuò)展 Acl 和 Ace 的功能,比如在 Ace 上面加上時(shí)間的條件限制,就需要自己定義 LookupStrategy,把時(shí)間條件從數(shù)據(jù)庫查詢出來,并放到自定義的 Ace 當(dāng)中。
但這件事情非常麻煩,因?yàn)槟J(rèn)實(shí)現(xiàn)的 BasicLookupStrategy 是個(gè) Final 的類,所以只能自己直接實(shí)現(xiàn)接口,無法使用現(xiàn)有的功能。
LookupStrategy 會(huì)生成 Acl,而最終的權(quán)限驗(yàn)證是由 Acl 完成的,如果想驗(yàn)證帶時(shí)間條件的 Ace,需要給 Acl 設(shè)置自定義的帶有檢查時(shí)間功能的 PermissionGrantingStrategy,實(shí)際上,這個(gè) PermissionGrantingStrategy 會(huì)首先設(shè)置給 LookupStrategy,LookupStrategy 在創(chuàng)建 Acl 的時(shí)候,再放到 Acl 中去。
f) SecurityExpressionHandler 能夠執(zhí)行 spel,得到是否可以訪問的結(jié)果,它的子類都是繼承自 AbstractSecurityExpressionHandler 的,有一個(gè)非常重要的方法是 SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, T invocation),創(chuàng)建一個(gè) SecurityExpressionOperations 放到 EvaluationContext 中去,提供 spel 中執(zhí)行的方法實(shí)現(xiàn)。比如 SecurityExpressionOperations 的一個(gè)抽象實(shí)現(xiàn) SecurityExpressionRoot 中,就包含了大量的權(quán)限驗(yàn)證方法,如 hasRole, hasPermission 等常用的功能。
g) AclService, MutableAclService, AclCache 概念比較簡單,AclService 是通過 LookupStrategy 查詢 Acl,自已可以查詢 ObjectIdentity 的父子關(guān)聯(lián)關(guān)系,MutableAclService 提供了修改的能力,AclCache 為 AclService 提供緩存,默認(rèn)的實(shí)現(xiàn)了一個(gè) EhCacheBasedAclCache。
3. ss 的鑒權(quán)模型 Sid, ObjectIdentity, Acl, Ace, Permission
a) Sid: 是中心,所有的授權(quán)會(huì)關(guān)聯(lián)在 Sid 上面,Sid 和之前的 Role Base Permission 會(huì)有些相同的地方,但也明顯不同,Sid 默認(rèn)實(shí)現(xiàn)情況下,分為 GrantedAuthoritySid 和 PrincipalSid,其實(shí)就是 Role 和 User,通過 SidRetrievalStrategy 拿到一個(gè) Authentication 的 Sid。
b) ObjectIdentity: 可以理解成 Resource,就是可訪問的目標(biāo)資源,有 id 和 type 兩個(gè)字段,默認(rèn)實(shí)現(xiàn)的 ObjectIdentityImpl 會(huì)直接調(diào)用目標(biāo) domainObject 的 getClass 和 getId 方法拿到兩個(gè)參數(shù)。在 PermissionEvaluator, AfterInvocationProvider 中,會(huì)用到 ObjectIdentityRetrievalStrategy 和 ObjectIdentityGenerator,ObjectIdentityRetrievalStrategy 會(huì)根據(jù) domainObject 拿到 ObjectIdentity,然后使用 Acl 進(jìn)行鑒權(quán),ObjectIdentityGenerator 會(huì)在系統(tǒng)提供的不是 domainObject,而是 type, id 的時(shí)候,拿到 ObjectIdentity,然后進(jìn)行 Acl 鑒權(quán),這兩個(gè)接口有一個(gè)共同的實(shí)現(xiàn) ObjectIdentityRetrievalStrategyImpl,如果需要在 ObjectIdentity 進(jìn)行新的抽象,需要用新的實(shí)現(xiàn),到得不同的 ObjectIdentity,比如將業(yè)務(wù)對象分類鑒權(quán)這樣的需求。
c) Acl, 每個(gè) ObjectIdentity 最多對應(yīng)一條 Acl,Acl 中包含了很多,包括 parental,說明 Acl 是有繼承關(guān)系的?其實(shí)不是,呵呵,是 ObjectIdentity 有繼承關(guān)系而已。有一個(gè) ObjectIdentity,有很多 Sid,還有一個(gè)叫做 Owner 的 Sid,有從 LookupStrategy 傳過來的 PermissionGrantingStrategy,進(jìn)行實(shí)際的鑒權(quán),還有 AclAuthorizationStrategy 檢查有沒有權(quán)限進(jìn)行 Acl security check。實(shí)現(xiàn)時(shí)間條件檢查,就擴(kuò)展 PermissionGrantingStrategy。
為什么沒有 RoleHierarchy 或是 SidRetrievalStrategy 存在呢?是因?yàn)檎{(diào)用 Acl 進(jìn)行權(quán)限檢查之前,已經(jīng)把相關(guān)的 Sid 得到了,再給 Acl 的。
d) Ace, Permission: Ace 存儲(chǔ) Sid, Permission,提供給 Acl 鑒權(quán)用。增加時(shí)間條件的話,最基本的,就是要在 Ace 中,增加時(shí)間條件字段。Permission 是用二進(jìn)制存儲(chǔ)的,但默認(rèn)實(shí)現(xiàn)的數(shù)據(jù)庫存儲(chǔ)并不是,是一個(gè)一條,存在數(shù)據(jù)庫里面的。
好吧,概念還是非常多的,不過鑒于權(quán)限控制本身就是個(gè)復(fù)雜的話題,ss 這些設(shè)計(jì)的我覺得已經(jīng)非常好,也基本夠用了。
@import url(http://www.aygfsteel.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);