本文假设你对Acegi其他部分已经比较熟悉。Acegi 的ACL控制是建立在对相应业务方法拦截的基础上的。这里以Acegi自带的contacts例子来说明。
先看看总的配置:
xml 代码
- <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>
该 拦截器实现了org.aopalliance.intercept.MethodInterceptor接口。在方法被调用之前,拦截器会先调用 AuthenticationManager判断用户身份是否已验证,然后从objectDefinitionSource中获取方法所对应的权限,再调 用AccessDecisionManager来匹配用户权限和方法对应的权限。如果用户没有足够权限调用当前方法,则抛出 AccessDeniedException使方法不能被调用。方法调用后会调用AfterInvocationManager对返回的结果进行再次处 理。下面依次说明。
AccessDecisionManager的配置:
xml 代码
- <bean id="businessAccessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased">
- <property name="allowIfAllAbstainDecisions"><value>falsevalue>property>
- <property name="decisionVoters">
- <list>
- <ref local="roleVoter"/>
- <ref local="aclContactReadVoter"/>
- <ref local="aclContactDeleteVoter"/>
- <ref local="aclContactAdminVoter"/>
- list>
- property>
- bean>
AccessDecisionManager 接口有decide()和support()方法。decide()方法决策是否批准通过即方法是否容许调用,如果没抛出 AccessDeniedException则为允许访问资源,否则拒绝访问。support()方法是根据配置属性和受保护资源的类来判断是否需要对该 资源作出决策判断。
AccessDecisionManager的 decisionVoters属性需要一个或多个Voter(投票者),Voter必须实现AccessDecisionVoter 接口。Voter的工作是去匹配用户已拥有的权限和受保护的资源要求的权限,在该资源有相应权限的情况下,如果匹配则投允许票,否则投反对票。
allowIfAllAbstainDecisions属性表示是否允许所有都弃权时就通过。Voter的实现类RoleVoter在当受保护资源的名字由ROLE_开始时才参与投票。
AccessDecisionManager有三个实现类,功能各不相同:
AffirmativeBased: 当至少有一个Voter投允许票时才通过
UnanimousBased: 没有Voter投反对票时才通过
ConsensusBased: 当所有Voter都投允许票时才通过
下面列出一个Voter的配置:
xml 代码
- <bean id="aclContactDeleteVoter" class="org.acegisecurity.vote.BasicAclEntryVoter">
- <property name="processConfigAttribute"><value>ACL_CONTACT_DELETEvalue>property>
- <property name="processDomainObjectClass"><value>sample.contact.Contactvalue>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
所 以在调用sample.contact.ContactManager.delete这个方法时aclContactDeleteVoter会参与投票, 它会获得sample.contact.Contact这个对象(这个对象从delete方法的参数中获得),然后通过aclManager去获得当前用 户对该Contact实例的ACL权限,最后拿这个权限与我们需要的权限比对,我们配置需要的权限是 org.acegisecurity.acl.basic.SimpleAclEntry.ADMINISTRATION和 org.acegisecurity.acl.basic.SimpleAclEntry.DELETE。如果我们通过aclManager获得的权限包 括这两个配置的权限之一,Voter就投容许票,方法容许调用。如果不包括,那对不起,反对票,AccessDecisionManager就会抛出 AccessDeniedException。方法拒绝调用。
AclManager的配置:
xml 代码
- <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只是一个接口,系统中一般都是造型为 BasicAclEntry。它包括了这个Entry所保护的domainObject instance(这里是Contact),实际它实现上是以AclObjectIdentity来替代这个domainObject的 (domainClass+domainObjectId);它包括了谁(Recipient)拥有这个domainObject instance以及他所对这个domainObject instance的操作权限(mask)。
一个domainObject instance对应了多个AclEntry,比如一条通讯录张三可以查看,而李四可以管理,一个Contact instance就对应了两个AclEntry,第一个AclEntry包含信息:所保护的domainObject(Contact),谁(张三),权 限(查看);第二个AclEntry包含信息:所保护的domainObject(Contact),谁(李四),权限(管理)。
这样AclManager的两个方法就很好理解了getAcls(Object domainInstance)返回所有这个domainInstance所对应的权限信息,
getAcls(Object domainInstance, Authentication authentication)在第一个方法返回结果的基础上做了过滤,过滤出和authentication(当前用户)相关的权限信息。如果当前用户 是张三,则返回与张三对应的记录。
这样Acegi就会拦截业务方法发挥相应的作用,但是在业务方法返回一个List或是单个 domainObject instance的时候,同样也是需要把用户没有权限查看的domainObject instance过滤掉的,这时就要用afterInvocationManager了,
看配置:
xml 代码
- <bean id="afterInvocationManager" class="org.acegisecurity.afterinvocation.AfterInvocationProviderManager">
- <property name="providers">
- <list>
- <ref local="afterAclRead"/>
- <ref local="afterAclCollectionRead"/>
- </list>
- </property>
- </bean>
-
-
- <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>
-
-
- <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的权限,如果和需要的权限不和,则过滤掉。呵呵,传说中的虎牙子就在此时产生了!
afterAclRead则依次类推。
参考了ss wiki里相关的文档,特别是差沙和cac的文档,写的相当好。另外acegi的代码也是相当的易读。
分享到:
相关推荐
- **依赖Spring框架**:Acegi基于Spring构建,这意味着应用必须先支持Spring框架才能使用Acegi。 - **学习曲线**:对于初次接触的开发者而言,Acegi的复杂性和灵活性可能会带来较高的学习成本。 #### 结论 Acegi...
2. **AspectJ Join Point**:使用AspectJ来管理Domain Object实例的安全,特别适合那些不在Spring Bean容器管理范围内的对象。通过Acegi,可以对标准构造函数(如`new Person()`)进行安全控制。 3. **...
在《实战Acegi:使用Acegi作为基于Spring框架的WEB应用的安全框架.pdf》中,可能会详细讲解如何配置和使用Acegi。以下是一些关键步骤: 1. **添加依赖**:首先,在项目中引入Acegi的依赖库,通常是通过Maven或...
在本实例中,我们将深入探讨如何使用Acegi来控制用户的权限。Acegi Security已经被Spring Security替代,但其核心思想和机制仍然适用于现代的Spring Security。 首先,我们需要理解Acegi的基础概念。Acegi的核心是`...
对于领域对象的访问,Acegi会在执行Bean方法前检查访问控制列表(ACL),确保用户有权操作该对象。 5. **体系结构** Acegi的核心组件包括AuthenticationManager负责身份认证,AccessDecisionManager负责访问控制...
首先,Acegi 提供了一种强大的方法来管理 Web 应用程序的安全性,它基于 ACL(Access Control List,访问控制列表)模型,允许开发者精细地控制谁可以访问哪些资源。Acegi 集成了认证(Authentication)和授权...
Acegi是Spring框架早期的一个安全模块,全称为Acegi Security System for Spring,它为Spring应用程序提供了...如果你正在使用或计划使用Spring Security,理解Acegi的笔记将有助于你更好地掌握这个强大的安全框架。
X509证书是公钥基础设施(PKI)的一部分,Acegi支持使用X509证书进行用户认证,这在需要高安全性的环境中非常有用。 7. **认证适配器**: Acegi为当前所有流行的Web应用服务器和容器提供了认证适配器,确保了它能...
我们可以使用 ACL(Access Control List)或者自定义策略来定义权限。例如,我们可以使用 `PreAuthorize` 或 `PostAuthorize` 注解在方法级别设置访问规则,或者使用 `hasRole` 或 `hasPermission` 表达式在 XML ...
2. **授权**:Acegi 使用 ACL(Access Control List)来实现细粒度的权限控制。ACL 可以定义哪些用户或角色对哪些资源有访问权限。此外,Acegi 还支持基于角色的访问控制(RBAC),通过角色分配来管理用户的权限。 ...
Spring Acegi 的授权机制基于 ACL(Access Control List),允许开发者对资源进行细粒度的权限控制。通过 `AccessDecisionManager` 和 `AccessDecisionVoter`,系统可以根据用户的角色和权限来决定是否允许访问特定...
它提供了多种认证和授权策略,包括基于URL的WEB资源访问控制、业务方法调用访问控制以及领域对象访问控制(ACL)。此外,它还支持单点登录(CAS)、信道安全管理和缓存功能。 2. **Acegi Security发展历程** Acegi...
2. **授权**:Acegi支持细粒度的权限控制,可以基于角色、表达式或者访问控制列表(ACL)进行授权。通过定义AccessDecisionManager和AccessDecisionVoter,你可以控制用户对资源的访问权限,比如允许或拒绝特定的...
通过这个示例,开发者可以学习到如何使用Acegi Security进行权限配置,包括设置安全性拦截器、创建自定义的认证和授权机制、处理未授权或未认证的异常、以及如何在控制器中检查用户权限等。此外,还能了解到如何在...
4. Access Control List (ACL):Acegi提供了基于对象实例的访问控制,允许根据对象的属性或状态来限制访问。例如,一个订单如果其价值小于100元,则所有用户都可以查看;但如果超过100元,就只有具有特定权限的用户...
授权部分,Acegi允许我们为每个URL、方法或者类定义访问控制列表(ACL),可以基于角色、权限或特定的表达式。例如,我们可以设置只有拥有“ADMIN”角色的用户才能访问某些管理页面。 此外,Acegi还提供了会话管理...
安全检查的具体逻辑通常包括权限判断、访问控制列表(Access Control List, ACL)等。 在安全检查完成后,`FilterSecurityInterceptor`会调用`FilterChain`的`doFilter()`方法,允许请求继续向下传递到下一个过滤器...