在前面的章节里,我们讨论了 Spring Security 如何实现「认证」,本节开始,我们进入 Spring Security 的「鉴权」部分。
鉴权(Authorization)是指验证用户是否拥有访问系统的权力,它的前提是用户的身份已经得到有效地认证,也是认证的目标。
Spring Security 提供的鉴权能力的最大特点是,无关于开发人员所选用的认证方式(密码认证、OAuth2.0 认证、证书认证等),即使它不是在 Spring Security 认证范围之内(预认证等),也可以简单快捷的基础 Spring Security 鉴权功能。
本节我们主要讨论 Spring Security 关于鉴权部分的实现思路。
Spring Security 中,在用户身份信息得到确认后,Authentication 中会存储一系列的 GrantedAuthority 对象,这些对象用来判断用户可以使用哪些资源。
GrantedAuthority 对象通过 AuthenticationManager 插入到 Authentication 对象中,并被 AccessDecisionManager 使用,判断其权限。
GrantedAuthority 是一个接口,其仅包含一个方法:
String getAuthority();
getAuthority()
方法返回一个字符串值,该值作为权限的描述,当权限较为复杂,不是字符串可以描述的情况时,该方法需要返回 null
。这种复杂的权限可能是「多种操作对应多个不同用户」等类似情况,用一个字符串很难表达完整,此时 AccessDecisionManager 会根据 getAuthority()
返回值情况判断是否要进行特殊处理。
在 Spring Security 中,GrantedAuthority 有一个基础实现类 SimpleGrantedAuthority
可以满足一般的业务需求。
Spring Security 的权限判断可以发生在方法被调用前,或者 WEB 请求之前。在请求的开始,由 AccessDecisionManager
对象将判断其是否允许继续执行。
AccessDecisionManager
对象由 AbstractSecurityInterceptor
发起调用,其职责是给出资源是否能被访问的最终结果,AccessDecisionManager
包含三个主要方法:
boolean supports(ConfigAttribute attribute);
boolean supports(Class clazz);
void decide(Authentication authentication, Object secureObject,
Collection<ConfigAttribute> attrs) throws AccessDeniedException;
Spring Security 的鉴权策略可以由用户自己实现,在 Spring Security 内部也实现了一套鉴权策略,称为「基于投票的访问决策管理」。
在这种策略下,AccessDecisionManager
控制着一系列的 AccessDecisionVoter
实例,判断权限是否满足,如果不满足抛出 AccessDeniedException
异常。
AccessDecisionVoter
也包含三个方法:
boolean supports(ConfigAttribute attribute);
boolean supports(Class clazz);
int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attrs);
投票鉴权分为三类:
有时候,权限的判断是在资源被调动之后才处理的,此过程就是后置鉴权。
在 Spring Security 中,后置鉴权通过 AfterInvocationManager
进行管理。
后置鉴权在资源被访问后,根据权限的判定来修改返回的内容,或者返回 AccessDeniedException
。
有时候,一个角色可能涵盖了多种其他角色。例如:admin 可能包含 user 的权限,为实现这一功能,我们可能会为 admin 用户增加 user 角色。
要实现这种配置,我们需要用到 RoleVoter 的扩展实现类,RoleHierarchyVoter
。其配置方式如下:
<bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
<constructor-arg ref="roleHierarchy" />
</bean>
<bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
<property name="hierarchy">
<value>
ROLE_ADMIN > ROLE_STAFF
ROLE_STAFF > ROLE_USER
ROLE_USER > ROLE_GUEST
</value>
</property>
</bean>
这个配置中出现了四种角色,ADMIN、STAFF、USER、GUEST,而这四种又有明显的包含于被包含关系,如此便可以使角色投票机制根据角色的层级进行决策。
本节我们讨论了 Spring Security 中鉴权的基本设计思路,主要内容如下:
下节我们讨论如何为 Servlet 应用提供鉴权能力。
0/1000