spring security(下簡寫為 ss)控制的安全主要有兩方面,Web 和 Method Call,這兩個方面的權限控制有比較多的相通的設計,也有一些特別的功能。比如 Method Call 可以做 After Invocation 控制,而 Web 可以做 Ip 地址控制。
這里面有兩個最基本的概念:authentication manager 和 access decision manager,前者控制認證,后都控制鑒權。
1. 在 ss 的認證系統中,默認的實現幫助我們提供了三個概念,用戶(user),角色(authority,一般存 role)和組(group),三者的關系是,組、角色與用戶都是多對多關系,組和角色間沒關系,默認是不啟用組的。后續,在 Acl 權限管理中,可以看到角色之間,是可以有包含(樹形?)關系的。
2. 在 ss 的鑒權系統中,明顯會比認證復雜得多。有 AccessDecisionManager, AccessDecisionVoter(前置), AfterInvocationProvider(后置), RoleHierarchy, SidRetrievalStrategy, LookupStrategy, PermissionGrantingStrategy, SecurityExpressionHandler, AclService, MutableAclService, AclCache 概念過多了,要一個一個解釋
a) 中心是 AccessDecisionManager,主要負責 AccessDecisionVoter 的管理,默認提供了3種實現:1. AffirmativeBased 如果有任何一個投票器允許訪問,請求將被立刻允許,而不管之前可能有的拒絕決定。2. ConsensusBased 多數票(允許或拒絕)決定了結果,平局的投票 和空票(全是棄權的)的結果是可配置的。3. UnanimousBased 所有的投票器必須全是允許的,否則訪問將 被拒絕。
AccessDecisionManager 在用于 Web 和 Method Call 兩種情況下,可能是不一致的,因為功能也不一致。
b) Method Call 除了使用 AccessDecisionManager 進行權限判斷外,還可以增加 AfterInvocationProvider 來進行出口數據的判斷,默認提供了 3 種。
1) PostInvocationAdviceProvider: 需要提供一個 PostInvocationAuthorizationAdvice,默認實現只有一個,就是 ExpressionBasedPostInvocationAdvice,可以通過 spel 來進行權限判斷。注意 ExpressionBasedPostInvocationAdvice 中需要提供一個 MethodSecurityExpressionHandler,能夠創建出一個 MethodSecurityExpressionOperations,放到 spel context 中,供 spel function 調用,這樣的方式,在后續很常見。
2) AclEntryAfterInvocationProvider 和 AclEntryAfterInvocationCollectionFilteringProvider : 這兩種都差不多,主要依賴 AclService, ObjectIdentityRetrievalStrategy, SidRetrievalStrategy 來配合,檢查返回值的權限。Collection 版本的,可以把無權限的數據去掉,只留下有權限的數據。
c) RoleHierarchy 提供了角色之間的關系,提供了兩個實現,一個是沒關系的,直接把 user 的 role 返回,另外一個是有繼承關系的。繼承關系實現挺有意思的,能夠處理多級的 include 關系,比較好用。
RoleHierarchy 的使用比較復雜,會被 AccessDecisionVoter, SidRetrievalStrategy, SecurityExpressionHandler 用到,SecurityExpressionHandler 又會被 AccessDecisionVoter 用到,所以還是有點兒混亂。
具體的說 SecurityExpressionHandler 會用到 PermissionEvaluator 和 RoleHierarchy,PermissionEvaluator 的一個實現 AclPermissionEvaluator 會用到 SidRetrievalStrategy。
d) SidRetrievalStrategy 和 RoleHierarchy 的功能比較接近,比 RoleHierarchy 高一個抽象層次,功能上也有所區別,是從一個 authentication 拿到所有相關的 Sid(包括 Role(GrantedAuthoritySid) 和 User(PrincipalSid)),而 RoleHierarchy 只包括了 Role(GrantedAuthoritySid)的繼承關系。
e) LookupStrategy 通過 ObjectIdentity 和 Sid 把相關的 Acl 查詢出來。可以在 LookupStrategy 擴展 Acl 和 Ace 的功能,比如在 Ace 上面加上時間的條件限制,就需要自己定義 LookupStrategy,把時間條件從數據庫查詢出來,并放到自定義的 Ace 當中。
但這件事情非常麻煩,因為默認實現的 BasicLookupStrategy 是個 Final 的類,所以只能自己直接實現接口,無法使用現有的功能。
LookupStrategy 會生成 Acl,而最終的權限驗證是由 Acl 完成的,如果想驗證帶時間條件的 Ace,需要給 Acl 設置自定義的帶有檢查時間功能的 PermissionGrantingStrategy,實際上,這個 PermissionGrantingStrategy 會首先設置給 LookupStrategy,LookupStrategy 在創建 Acl 的時候,再放到 Acl 中去。
f) SecurityExpressionHandler 能夠執行 spel,得到是否可以訪問的結果,它的子類都是繼承自 AbstractSecurityExpressionHandler 的,有一個非常重要的方法是 SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, T invocation),創建一個 SecurityExpressionOperations 放到 EvaluationContext 中去,提供 spel 中執行的方法實現。比如 SecurityExpressionOperations 的一個抽象實現 SecurityExpressionRoot 中,就包含了大量的權限驗證方法,如 hasRole, hasPermission 等常用的功能。
g) AclService, MutableAclService, AclCache 概念比較簡單,AclService 是通過 LookupStrategy 查詢 Acl,自已可以查詢 ObjectIdentity 的父子關聯關系,MutableAclService 提供了修改的能力,AclCache 為 AclService 提供緩存,默認的實現了一個 EhCacheBasedAclCache。
3. ss 的鑒權模型 Sid, ObjectIdentity, Acl, Ace, Permission
a) Sid: 是中心,所有的授權會關聯在 Sid 上面,Sid 和之前的 Role Base Permission 會有些相同的地方,但也明顯不同,Sid 默認實現情況下,分為 GrantedAuthoritySid 和 PrincipalSid,其實就是 Role 和 User,通過 SidRetrievalStrategy 拿到一個 Authentication 的 Sid。
b) ObjectIdentity: 可以理解成 Resource,就是可訪問的目標資源,有 id 和 type 兩個字段,默認實現的 ObjectIdentityImpl 會直接調用目標 domainObject 的 getClass 和 getId 方法拿到兩個參數。在 PermissionEvaluator, AfterInvocationProvider 中,會用到 ObjectIdentityRetrievalStrategy 和 ObjectIdentityGenerator,ObjectIdentityRetrievalStrategy 會根據 domainObject 拿到 ObjectIdentity,然后使用 Acl 進行鑒權,ObjectIdentityGenerator 會在系統提供的不是 domainObject,而是 type, id 的時候,拿到 ObjectIdentity,然后進行 Acl 鑒權,這兩個接口有一個共同的實現 ObjectIdentityRetrievalStrategyImpl,如果需要在 ObjectIdentity 進行新的抽象,需要用新的實現,到得不同的 ObjectIdentity,比如將業務對象分類鑒權這樣的需求。
c) Acl, 每個 ObjectIdentity 最多對應一條 Acl,Acl 中包含了很多,包括 parental,說明 Acl 是有繼承關系的?其實不是,呵呵,是 ObjectIdentity 有繼承關系而已。有一個 ObjectIdentity,有很多 Sid,還有一個叫做 Owner 的 Sid,有從 LookupStrategy 傳過來的 PermissionGrantingStrategy,進行實際的鑒權,還有 AclAuthorizationStrategy 檢查有沒有權限進行 Acl security check。實現時間條件檢查,就擴展 PermissionGrantingStrategy。
為什么沒有 RoleHierarchy 或是 SidRetrievalStrategy 存在呢?是因為調用 Acl 進行權限檢查之前,已經把相關的 Sid 得到了,再給 Acl 的。
d) Ace, Permission: Ace 存儲 Sid, Permission,提供給 Acl 鑒權用。增加時間條件的話,最基本的,就是要在 Ace 中,增加時間條件字段。Permission 是用二進制存儲的,但默認實現的數據庫存儲并不是,是一個一條,存在數據庫里面的。
好吧,概念還是非常多的,不過鑒于權限控制本身就是個復雜的話題,ss 這些設計的我覺得已經非常好,也基本夠用了。
@import url(http://www.tkk7.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
posted on 2013-11-12 14:25
哈哈的日子 閱讀(659)
評論(0) 編輯 收藏