15.Spring Security应用详解-工作原理-授权流程
2020-03-25 本文已影响0人
LANSHENGYANG
授权流程
授权流程
- 通过快速上手我们知道,Spring Security可以通过http.authorizeRequests()对web请求进行授权保护。Spring Security使用标准Filter建立了对web请求的拦截,最终实现对资源的授权访问。
-
Spring Security的授权流程如下:
image
分析授权流程:
- 1.拦截请求,已认证用户访问保护的web资源将被SecurityFilterChain中的
FilterSecurityInterceptor
的子类拦截。 - 2.获取资源访问策略,FilterSecurityInterceptor会从
SecurityMetadataSource
的子类DefaultFilterInvocationSecurityMetadataSource
获取要访问当前资源所需要的权限Collection<ConfigAttribute>
。 - SecurityMetadataSource其实就是读取访问策略的抽象,而读取的内容,其实就是我们配置的访问规则,读取访问策略如:
http
.authorizeRequests()
.antMatchers("/r/r1").hasAuthority("p1")
.antMatchers("/r/r2").hasAuthority("p2")
...
- 3.最后。FilterSecurityInterceptor会调用
AccessDecisionManager
进行授权决策,若决策通过,则允许访问资源,否则将禁止访问。 - AccessDecisionManager(访问资源管理器)的核心接口如下:
public class AccessDecisionManager {
/**
* 通过传递的参数来决定用户是否访问对应受保护资源的权限
* @param authentication
* @param object
* @param configAttributes
*/
void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes){、
//略..
}
}
- 这里着重说明一下decide的参数:
- authentication:要访问资源的访问者的身份
- object:要访问的受保护资源,web请求对应FilterInvocation
- configAttributes:受保护资源的访问策略,通过SecurityMetadataSource获取
- decide接口就是用来鉴定当前用户是否访问对应受保护资源的权限。
授权决策
-
AccessDecisionManager采用投票的方式来确定是否能够访问受保护资源。
-
通过上图可以看出,AccessDecisionManager中包含的一系列AccessDecisionVoter将会被用来对Authentication是否有权限访问受保护对象进行投票,AccessDecisionManager根据投票结果,做出最终决策。
-
AccessDecisionVoter是一个接口,其中定义有三个方法,具体结构如下所示。
public interface AccessDecisionVoter<S> {
int ACCESS_GRANTED = 1;
int ACCESS_ABSTAIN = 0;
int ACCESS_DENIED = -1;
boolean supports(ConfigAttribute attribute);
boolean supports(Class<?> clazz);
int vote(Authentication authentication, S object, Collection<ConfigAttribute> attributes);
}
-
vote()方法的返回结果会是AccessDecisionVoter中定义的三个常量之一。ACCESS_GRANTED表示同意,ACCESS_DENIED表示拒绝,ACCESS_ABSTAIN表达弃权。如果一个AccessDecisionVoter不能判定当前Authentication是否拥有访问对应受保护对象的权限,则其vote()方法的返回值当弃权ACCESS_ABSTAIN。
-
Spring Security内置了三个基于投票的AccessDecisionManager实现类如下,它们分别是AffirmativeBased,ConsensusBased和UnanimousBased。
- AffirmativeBased的逻辑是:
(1)如果赞成票多反对票则表示通过。
(2)反过来,如果反对票多赞成票则将抛出AccessDeniedException。
(3)如果赞成票与反对票相同且不等于0,并且属性allowlfEqualGrantedDeniedDecisions的值为true,则表示通过,否则将抛出异常AccessDeniedException。参数allowlfEqualGranedDeniedDecision的值默认为true。
(4)如果所有的AccessDecisionVoter都弃权了,则将视参数allowlfAllAbstainDecisions的值而定,如果该值为true则表示通过,否则将抛出异常AccessDeniedException。参数allowlfAllAbstainDecisions的值默认为false。
- AffirmativeBased的逻辑是: