在Acegi中使用ACL

在Acegi中使用ACL(转)

Acegi好早就实现了ACL(好像是0.5),但是使用起来确实有点麻烦,所以用的不是太广泛。这里简单的说明一下使用方法,希望有更多的朋友来试试。

首先要理解Acegi里面Voter的概念,ACL正是在一个Voter上扩展起来的。现来看一下AclVoter的配置。

     < bean  id ="aclBeanReadVoter"  class ="org.acegisecurity.vote.BasicAclEntryVoter" >
        
< property  name ="processConfigAttribute" >
            
< value > ACL_READ </ value >
        
</ property >
        
< property  name ="processDomainObjectClass" >
            
< value > org.springside.modules.security.acl.domain.AclDomainAware </ 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.READ" />
            
</ list >
        
</ property >
    
</ bean >
  1. ACL_READ指的是这个Voter对哪些SecurityConfig起作用,我们可以把ACL_READ配置在想要拦截的Method上。比方说我们要拦截readOrder这个方法,以实现ACL控制,可以这样配置。
    orderManager.readOrder=ACL_READ
  2. processDomainObjectClass指出哪些DomainObject是要进行ACL校验的。
  3. aclManager是一个比较重要的概念,主要负责在权限列表中根据用户和DomainObject取得acl列表。
  4. requirePermission指出要进行这个操作必须具备的acl权限,比方说read操作就必须有ADMINISTRATION或READ两个权限。

其实整个过程看下来比较清晰,下面来看一下AclManager如何配置。

     <!--  ========= ACCESS CONTROL LIST LOOKUP MANAGER DEFINITIONS =========  -->

    
< 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继承了Acegi的一贯风格,Provider可以提供多种取得ACL访问列表的途径,默认的是用 basicAclProvider 在数据库中取得。既然提到了数据库,那我们就来看一下Acegi默认提供的ACL在数据库里的保存表结构:

CREATE   TABLE  acl_object_identity (
id 
IDENTITY   NOT   NULL ,
object_identity VARCHAR_IGNORECASE(
250 NOT   NULL ,
parent_object 
INTEGER ,
acl_class VARCHAR_IGNORECASE(
250 NOT   NULL ,
CONSTRAINT  unique_object_identity  UNIQUE (object_identity),
FOREIGN   KEY  (parent_object)  REFERENCES  acl_object_identity(id)
);
CREATE   TABLE  acl_permission (
id 
IDENTITY   NOT   NULL ,
acl_object_identity 
INTEGER   NOT   NULL ,
recipient VARCHAR_IGNORECASE(
100 NOT   NULL ,
mask 
INTEGER   NOT   NULL ,
CONSTRAINT  unique_recipient  UNIQUE (acl_object_identity, recipient),
FOREIGN   KEY  (acl_object_identity)  REFERENCES  acl_object_identity(id)
);
  1. acl_object_identity表存放了所有受保护的domainObject的信息。其中object_identity字段保存了domainObject的class和id,默认的保存格式是:domainClass:domainObjectId。
  2. acl_permission 就是ACL权限列表了,recipient 是用户或角色信息,mask表示了这个用户或角色对这个domainObject的访问权限。注意这些信息的保存格式都是可以根据自己的需要改变的。

这样读取和删除的时候Acegi就能很好的完成拦截工作,但是读取一个List的时候,如何才能把该用户不能操作的domainObject剔除掉呢?这就需要afterInvocationManager来完成这个工作。下面来看下配置:

     <!--  ============== "AFTER INTERCEPTION" AUTHORIZATION DEFINITIONS ===========  -->

    
< bean  id ="afterInvocationManager"  class ="org.acegisecurity.afterinvocation.AfterInvocationProviderManager" >
        
< property  name ="providers" >
            
< list >
                
< 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 >

afterAclCollectionRead会在拦截的方法执行结束的时候执行。主要的作用就是在返回的List中挨个检查domainObject的操作权限,然后根据requirePermission来剔除不符合的domainObject。

你可能感兴趣的:(在Acegi中使用ACL)