Junky's IT Notebook

          統(tǒng)計

          留言簿(8)

          積分與排名

          WebSphere Studio

          閱讀排行榜

          評論排行榜

          Acegi ACL使用說明

          本文假設你對Acegi其他部分已經(jīng)比較熟悉。Acegi 的ACL控制是建立在對相應業(yè)務方法攔截的基礎(chǔ)上的。這里以Acegi自帶的contacts例子來說明。
          先看看總的配置

          <bean id="contactManagerSecurity" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
                
          <property name="authenticationManager"><ref bean="authenticationManager"/></property>
                
          <property name="accessDecisionManager"><ref local="businessAccessDecisionManager"/></property>
                
          <property name="afterInvocationManager"><ref local="afterInvocationManager"/></property>
                
          <property name="objectDefinitionSource">
                   
          <value>
                       sample.contact.ContactManager.getAll=AFTER_ACL_COLLECTION_READ
                       sample.contact.ContactManager.getById=AFTER_ACL_READ
                       sample.contact.ContactManager.delete=ACL_CONTACT_DELETE
                       sample.contact.ContactManager.deletePermission=ACL_CONTACT_ADMIN
                       sample.contact.ContactManager.addPermission=ACL_CONTACT_ADMIN
                   
          </value>
                
          </property>
             
          </bean>
          該攔截器實現(xiàn)了org.aopalliance.intercept.MethodInterceptor接口。在方法被調(diào)用之前,攔截器會先調(diào)用 AuthenticationManager判斷用戶身份是否已驗證,然后從objectDefinitionSource中獲取方法所對應的權(quán)限,再調(diào)用AccessDecisionManager來匹配用戶權(quán)限和方法對應的權(quán)限。如果用戶沒有足夠權(quán)限調(diào)用當前方法,則拋出 AccessDeniedException使方法不能被調(diào)用。方法調(diào)用后會調(diào)用AfterInvocationManager對返回的結(jié)果進行再次處理。下面依次說明。
          AccessDecisionManager的配置
          <bean id="businessAccessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased">
                
          <property name="allowIfAllAbstainDecisions"><value>false</value></property>
                
          <property name="decisionVoters">
                   
          <list>
                      
          <ref local="roleVoter"/>
                      
          <ref local="aclContactReadVoter"/>
                      
          <ref local="aclContactDeleteVoter"/>
                      
          <ref local="aclContactAdminVoter"/>
                   
          </list>
                
          </property>
             
          </bean>
          AccessDecisionManager 接口有decide()和support()方法。decide()方法決策是否批準通過即方法是否容許調(diào)用,如果沒拋出 AccessDeniedException則為允許訪問資源,否則拒絕訪問。support()方法是根據(jù)配置屬性和受保護資源的類來判斷是否需要對該資源作出決策判斷。
          AccessDecisionManager的 decisionVoters屬性需要一個或多個Voter(投票者),Voter必須實現(xiàn)AccessDecisionVoter 接口。Voter的工作是去匹配用戶已擁有的權(quán)限和受保護的資源要求的權(quán)限,在該資源有相應權(quán)限的情況下,如果匹配則投允許票,否則投反對票。
          allowIfAllAbstainDecisions屬性表示是否允許所有都棄權(quán)時就通過。Voter的實現(xiàn)類RoleVoter在當受保護資源的名字由ROLE_開始時才參與投票。
          AccessDecisionManager有三個實現(xiàn)類,功能各不相同:
          AffirmativeBased: 當至少有一個Voter投允許票時才通過
          UnanimousBased: 沒有Voter投反對票時才通過
          ConsensusBased: 當所有Voter都投允許票時才通過
          下面列出一個Voter的配置
          <bean id="aclContactDeleteVoter" class="org.acegisecurity.vote.BasicAclEntryVoter">
                
          <property name="processConfigAttribute"><value>ACL_CONTACT_DELETE</value></property>
                
          <property name="processDomainObjectClass"><value>sample.contact.Contact</value></property>
                
          <property name="aclManager"><ref local="aclManager"/></property>
                
          <property name="requirePermission">
                  
          <list>
                    
          <ref local="org.acegisecurity.acl.basic.SimpleAclEntry.ADMINISTRATION"/>
                    
          <ref local="org.acegisecurity.acl.basic.SimpleAclEntry.DELETE"/>
                  
          </list>
                
          </property>
             
          </bean>
          上面第一個配置里有這么一行:sample.contact.ContactManager.delete=ACL_CONTACT_DELETE
          所以在調(diào)用sample.contact.ContactManager.delete這個方法時aclContactDeleteVoter會參與投票,它會獲得sample.contact.Contact這個對象(這個對象從delete方法的參數(shù)中獲得),然后通過aclManager去獲得當前用戶對該Contact實例的ACL權(quán)限,最后拿這個權(quán)限與我們需要的權(quán)限比對,我們配置需要的權(quán)限是 org.acegisecurity.acl.basic.SimpleAclEntry.ADMINISTRATION和 org.acegisecurity.acl.basic.SimpleAclEntry.DELETE。如果我們通過aclManager獲得的權(quán)限包括這兩個配置的權(quán)限之一,Voter就投容許票,方法容許調(diào)用。如果不包括,那對不起,反對票,AccessDecisionManager就會拋出 AccessDeniedException。方法拒絕調(diào)用。
          AclManager的配置
          <bean id="aclManager" class="org.acegisecurity.acl.AclProviderManager">
                
          <property name="providers">
                   
          <list>
                      
          <ref local="basicAclProvider"/>
                   
          </list>
                
          </property>
             
          </bean>

             
          <bean id="basicAclProvider" class="org.acegisecurity.acl.basic.BasicAclProvider">
                
          <property name="basicAclDao"><ref local="basicAclExtendedDao"/></property>
             
          </bean>

             
          <bean id="basicAclExtendedDao" class="org.acegisecurity.acl.basic.jdbc.JdbcExtendedDaoImpl">
                
          <property name="dataSource"><ref bean="dataSource"/></property>
             
          </bean>
          AclManager是整個ACL中一個很核心的概念,它包含了兩個方法AclEntry[] getAcls(Object domainInstance)和
          AclEntry[] getAcls(Object domainInstance, Authentication authentication)。在了解這兩個方法前,我們先了解AclEntry這個對象。AclEntry只是一個接口,系統(tǒng)中一般都是造型為 BasicAclEntry。它包括了這個Entry所保護的domainObject instance(這里是Contact),實際它實現(xiàn)上是以AclObjectIdentity來替代這個domainObject的(domainClass+domainObjectId);它包括了誰(Recipient)擁有這個domainObject instance以及他所對這個domainObject instance的操作權(quán)限(mask)。
          一個domainObject instance對應了多個AclEntry,比如一條通訊錄張三可以查看,而李四可以管理,一個Contact instance就對應了兩個AclEntry,第一個AclEntry包含信息:所保護的domainObject(Contact),誰(張三),權(quán)限(查看);第二個AclEntry包含信息:所保護的domainObject(Contact),誰(李四),權(quán)限(管理)。
          這樣AclManager的兩個方法就很好理解了getAcls(Object domainInstance)返回所有這個domainInstance所對應的權(quán)限信息,
          getAcls(Object domainInstance, Authentication authentication)在第一個方法返回結(jié)果的基礎(chǔ)上做了過濾,過濾出和authentication(當前用戶)相關(guān)的權(quán)限信息。如果當前用戶是張三,則返回與張三對應的記錄。

          這樣Acegi就會攔截業(yè)務方法發(fā)揮相應的作用,但是在業(yè)務方法返回一個List或是單個 domainObject instance的時候,同樣也是需要把用戶沒有權(quán)限查看的domainObject instance過濾掉的,這時就要用afterInvocationManager了,看配置
          <bean id="afterInvocationManager" class="org.acegisecurity.afterinvocation.AfterInvocationProviderManager">
                
          <property name="providers">
                   
          <list>
                      
          <ref local="afterAclRead"/>
                      
          <ref local="afterAclCollectionRead"/>
                   
          </list>
                
          </property>
             
          </bean>
             
             
          <!-- Processes AFTER_ACL_COLLECTION_READ configuration settings -->
             
          <bean id="afterAclCollectionRead" class="org.acegisecurity.afterinvocation.BasicAclEntryAfterInvocationCollectionFilteringProvider">
                
          <property name="aclManager"><ref local="aclManager"/></property>
                
          <property name="requirePermission">
                  
          <list>
                    
          <ref local="org.acegisecurity.acl.basic.SimpleAclEntry.ADMINISTRATION"/>
                    
          <ref local="org.acegisecurity.acl.basic.SimpleAclEntry.READ"/>
                  
          </list>
                
          </property>
             
          </bean>
             
             
          <!-- Processes AFTER_ACL_READ configuration settings -->
             
          <bean id="afterAclRead" class="org.acegisecurity.afterinvocation.BasicAclEntryAfterInvocationProvider">
                
          <property name="aclManager"><ref local="aclManager"/></property>
                
          <property name="requirePermission">
                  
          <list>
                    
          <ref local="org.acegisecurity.acl.basic.SimpleAclEntry.ADMINISTRATION"/>
                    
          <ref local="org.acegisecurity.acl.basic.SimpleAclEntry.READ"/>
                  
          </list>
                
          </property>
             
          </bean>
          afterAclCollectionRead 會對配置AFTER_ACL_COLLECTION_READ的方法進行攔截,這里是 sample.contact.ContactManager.getAll方法,它會遍歷方法返回的domainObject,然后挨個通過 aclManager判斷當前用戶對domainObject的權(quán)限,如果和需要的權(quán)限不和,則過濾掉。呵呵,傳說中的虎牙子就在此時產(chǎn)生了!
          afterAclRead則依次類推。
          參考了ss wiki里相關(guān)的文檔,特別是差沙和cac的文檔,寫的相當好。另外acegi的代碼也是相當?shù)囊鬃x。

          posted on 2007-07-03 10:39 junky 閱讀(800) 評論(0)  編輯  收藏 所屬分類: security

          主站蜘蛛池模板: 沅陵县| 多伦县| 西充县| 桃源县| 襄樊市| 达日县| 焦作市| 铁岭县| 年辖:市辖区| 新闻| 镇江市| 金坛市| 沈阳市| 化德县| 竹北市| 秦皇岛市| 六盘水市| 阜康市| 澄迈县| 冕宁县| 莱阳市| 商水县| 沾化县| 洞口县| 田林县| 五莲县| 福建省| 黄石市| 连山| 黎川县| 河间市| 尼玛县| 谷城县| 石泉县| 安远县| 防城港市| 张掖市| 方正县| 铜山县| 蒙阴县| 龙门县|