SpringSecurity(二) :授权流程

一、授权流程

Spring Security可以通过 http.authorizeRequests()web请求进行授权保护。 Spring Security使用标准 Filter建立了对 web请求的拦截,最终对资源的授权访问。

Spring Security的授权流程如下:


分析授权流程:

  1. 拦截请求,已认证用户访问受保护的 web资源被 SpringFilterChain中的 FilterSecurityInterceptor的子类拦截。

  2. 获取资源访问策略FilterSecurityInterceptor会从 SecurityMetadataSource的子类 DefaultFilterInvocationSecurityMetadataSource获取要访问当前资源所需要的权限 Collection<configattribute></configattribute>

SecurityMetadataSource读取访问策略的抽象,而读取的内容,就是我们配置的访问规则,读取的访问策略如:

http
.authorizeRequests() .antMatchers("/r/r1").hasAuthority("p1")
.antMatchers("/r/r2").hasAuthority("p2")
...

  1. FilterSecurityInterceptor会调用 AccessDecisionManager进行授权决策,若决策通过,则允许访问资 源,否则将禁止访问。

1.1 AccessDecisionManager

AccessDecisionManager接口定义:

public interface AccessDecisionManager {
    void decide(Authentication var1, Object var2,
    	Collection<ConfigAttribute> var3)
    	throws AccessDeniedException,
    	InsufficientAuthenticationException;
    boolean supports(ConfigAttribute var1);
    boolean supports(Class<?> var1);
}

decide()方法是 AccessDecisionManager的核心, 用来鉴定当前用户是否有访问对应受保护资源的权限,其中参数:

var1:要访问资源的访问者的身份

var2:要访问的受保护资源,web请求对应 FilterInvocation

var3:是受保护资源的访问策略,通过 SecurityMetadatasource

1.2 授权决策

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 var1);

    boolean supports(Class<?> var1);

    int vote(Authentication var1, S var2,
     Collection<ConfigAttribute> var3);
}

vote()的返回结果会是 AccessDecisionVoter中定义的三个常量之一。 ACCESS_GRANTED表示同意, ACCESS_DENIED表示拒绝, ACCESS_ABSTAIN表示弃权。如果 AccessDecisionVoter不能判定当前 Authentication是否拥有访问对应受保护对象的权限,则 vote()方法的返回值为 ACCESS_ABSTAIN

Spring Security内置了三个基于投票的 AccessDecisionManager实现类如下,它们分别是 AffirmativeBasedConsensusBasedUnaimousBasedSpring Security默认使用的是 AffirmativeBased

​1、AffirmativeBased:

①只要有 AccessDecisionVoter的投票为 ACCESS_GRANTED则同意用户进行访问;

②如果全部弃权也表示通过;

③如果没有一个投赞成票,但是有人投反对票,则将抛出 AccessDeniedException

​2、ConsensusBased:

①如果赞成票多余反对票则表示通过;

②如果反对票多于赞成票则将抛出 AccessDeniedException

③如果赞成票与反对票相同且不等于0,并且属性 allowEqualGrantedDeniedDecision的值为true,则表示通过,否则将抛出 AccessDeniedExceptionallowEqualGrantedDeniedDecision的默认值为true。

④如果所有的 AccessDecisionVoter都弃权了,则将视参数 allowIfAllAbstainDecisions的值而定,如果该值为true则表示通过,否则将抛出异常 AccessDeniedException。参数 allowIfAllAbstainDecisions的值默认为false。

3、UnanimousBased:

UnanimousBased的逻辑与另外两种实现有点不一样,另外两种会一次性把受保护对象的配置属性全部传递给 AccessDecisionVoter进行投票,而 UnanimousBased会一次只传递一个 ConfigAttributeAccessDecisionVoter进行投票。这也就意味着如果我们的 AccessDecisionVoter的逻辑是只要传递进来的 ConfigAttribute中有一个能够匹配则投赞成票,但是放到 UnanimousBased中其投票结果就不一定是赞成了。 UnanimousBased的逻辑具体来说是这样的:
①如果受保护对象配置的某一个 ConfigAttribute被任意的 AccessDecisionVoter反对了,则将抛出 AccessDeniedException

②如果没有反对票,但是有赞成票,则表示通过。

③如果全部弃权了,则将视参数 allowIfAllAbstainDecisions的值而定,true则通过,false则抛出 AccessDeniedException

Spring Security也内置一些投票者实现类如 RoleVoterAuthenticatedVoterWebExpressionVoter等。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘架构

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值