在Spring Security 3.1的认证机制文中讲到了认证和授权是安全管理的两大主要内容。文中介绍了认证部分,这里重点介绍下ss3中的授权机制。如图:
Spring Security 3.1 的过滤器机制中,我们已介绍了SS3所有功能的实现都是基于filter。对于授权部分,其入口filter是FilterSecurityInterceptor,FilterSecurityInterceptor是spring提供的AbstractSecurityInterceptor抽象类的具体实现。授
权的主要逻辑在AbstractSecurityInterceptor中。该类定义了三个依赖接口,分别是AuthenticationManager、
AccessDecisionManager和SecurityMetadataSource。
首先,AbstractSecurityInterceptor需要得到用户所拥有的权限,它从SecurityContextHolder中得到登录用户的authentication,Spring Security 3.1的认证机制文中我们介绍了,authentication包含了用户的权限Authorities,如果未得到authentication,就会调用AuthenticationManager的authenticate方法进行认证,获得authentication。
接着,AbstractSecurityInterceptor还需要得到资源的权限,它调用SecurityMetadataSource中的Collection<ConfigAttribute>getAttributes(Object object)方法得到资源的权限集合Collection<ConfigAttribute>。
最后调用AccessDecisionManager的decide()方法进行授权判断,没有授权将抛出AccessDeniedException异常。
从图中可以看出,DefaultFilterInvocationSecurityMetadataSource是SS3提供的SecurityMetadataSource缺省实现,其将解读安全配置文件中类似如下的资源权限配置。
<intercept-url pattern="/**" access="ROLE_USER" />
如果我们利用数据库存储资源的权限配置,则应该自己实现SecurityMetadataSource接口,重点实现Collection<ConfigAttribute>getAttributes(Object object)方法。
SS3对AccessDecisionManager的实现采用的是投票机制,具体的投票工作由AccessDecisionVoter完成,RoleVoter是其具体实现。在RoleVoter中,规定了权限名称需以"ROLE_"开头。
private String rolePrefix = "ROLE_";
具体的投票在vote方法中,如下:
public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
int result = ACCESS_ABSTAIN;
Collection<? extends GrantedAuthority> authorities = extractAuthorities(authentication);
for (ConfigAttribute attribute : attributes) {
if (this.supports(attribute)) {
result = ACCESS_DENIED;
// Attempt to find a matching granted authority
for (GrantedAuthority authority : authorities) {
if (attribute.getAttribute().equals(authority.getAuthority())) {
return ACCESS_GRANTED;
}
}
}
}
return result;
}
对于每一AccessDecisionVoter投票结果统计的最终决策,SS3提供了三种实现策略:
ConsensusBased 通过票大于不通过票即通过
UnanimousBased 有一票通过即通过
AffirmativeBased 所有票都通过即通过,最常用,缺省用此类。
整个授权部分涉及的主要类全称如下:
org.springframework.security.access.intercept.AbstractSecurityInterceptor
org.springframework.security.web.access.intercept.FilterSecurityInterceptor
org.springframework.security.access.AccessDecisionManager
org.springframework.security.access.vote.AbstractAccessDecisionManager
org.springframework.security.access.AccessDecisionVoter<S>
org.springframework.security.access.vote.RoleVoter
org.springframework.security.access.vote.ConsensusBased
org.springframework.security.access.vote.UnanimousBased
org.springframework.security.access.vote.AffirmativeBased
org.springframework.security.access.SecurityMetadataSource
org.springframework.security.access.ConfigAttribute
org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource
org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource