Acegi Authorization 授权机制(2007-06-11 18:22:38)
身份验证主要是根据用户的信息,在数据库(或其他方式)获得其权限信息,并把它放到SecurityContext里面(权限信息被封装成GrantedAuthority数组,由AuthenticationManager放到代表用户的Authentication里),而并不决定对资源的真正访问权。用户对资源的访问权是由授权机制来控制的。
Acegi中,管理授权机制的是AccessDecisionManager。AccessDecisionManager采用民主决策机制判断用户是否有权访问目标程序资源,它包含了多个AccessDecisionVoter。在访问决策时每个AccessDecisionVoter都拥有投票权,AccessDecisionManager统计投票结果,并按照某种决策方式根据这些投票结果决定最终是否向用户开放受限资源的访问。
Acegi的投票方式有多种,每个Voter对访问权可以投赞成,弃权或反对,当然,我们除了使用Acegi自带的Voter(org.acegisecurity.vote.RoleVoter)外,我们还可以有自定义的Voter。甚至我们可以编写自己的AccessDecisionManager来管理投票(如给某项投票分配一定的权重)。
GrantedAuthority接口仅有如下方法,AccessDecisionManager通过这个方法获
| public String getAuthority(); |
得权限信息。
AbstractSecurityInterceptor调用AccessDecisionManager来做最终的资源访问控制的决定。下面我们来仔细看一下AccessDecisionManager这个接口,它包含如下三个方法:
|
public void decide(Authentication authentication, Object
object, ConfigAttributeDefinition config) throws AccessDeniedException;
public boolean supports(ConfigAttribute attribute);
public boolean supports(Class clazz);
|
这个接口的主要方法是decide,从参数我们可以看出它包含了所有“有价值”的信息。如果访问被拒绝的话,会抛出一个AccessDeniedException。Acegi的灵活之处是用户可以根据自己情况来实现AccessDecisionManager及投票制度。当然,系统也提供了几个很好用的实现,使得我们大部分情况下使用Acegi提供的类就够了,下面这张类图完整的表达了AccessDecisionManager的层次关系(如不清晰,可点击图片后在查看)。
AccessDecisionVoter除了上面的三个方法外,还有三个静态常量,这些常量就是vote返回的int值。
int ACCESS_GRANTED = 1;
int ACCESS_ABSTAIN = 0;
int ACCESS_DENIED = -1; |
Acegi提供了三个具体的类去管理投票结果,他们三个的不同存在于对投票结果的统计上。ConsensusBased类根据非弃权票中同意和反对的数量来决定是否通过。在同意和反对票相同时或都投弃权票时可以根据设置来决定授权与否。AffirmativeBased类只要有一个或多个投票赞成就会给予通过,同样我们可以设置在都投弃权票的时候是否通过。UnanimousBased类会在所有的非弃权票都投赞成票时才通过,同样的设置出现在都投弃权票的时候。
Acegi提供了AccessDecisionVoter的两个实现类。对于RoleVoter,我们需要配置它的rolePrefix属性(如ROLE_),当ConfigAttribute以rolePrefix开头时,RoleVoter才投票,否则投弃权票(ACCESS_ABSTAIN)。开始投票时,如果存在一个GrantedAuthority和被访问资源的一个或多个ConfigAttributes完全匹配时,投赞成票,否则投反对票。
After
Invocation
Handling
AbstractSecurityInterceptor调用AccessDecisionManager来决定资源(业务或domain对象)的访问。有时候,我们还需要在访问资源后进行一些操作,例如对返回数据的再加工。实际上,在Spring里使用AOP是很容易实现的,但Acegi提供了更加方便的类使我们对访问后资源进行操作。
同访问前控制类似,访问后控制由AfterInvocationManager管理,下面是它的实现类图:

可以看到,AfterInvocationManager接口和AccessDecisionManager接口有着相似的方法。需要注意的是,AfterInvocationManager的decide方法的参数包含了一个returnedObject,这个就是业务方法执行后返回的结果,我们可以对其进行再次的加工。
AfterInvocationProviderManager是用于管理Provider的,我们可以配置多个Provider,每个Provider都个对返回结果进行操作,操作顺序由配置顺序决定。上一个Provider的结果会传到下一个Provider。
配置完AfterInvocationProviderManager,一定要把它注入到MethodSecurityInterceptor里。
加载中,请稍候...