【微服务|Spring Security⑭】spring security授权流程

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

Spring Security的授权流程如下:

【微服务|Spring Security⑭】spring security授权流程

分析授权流程:

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

2.获取资源访问策略,FilterSecurityInterceptor会从 SecurityMetadataSource 的子类 DefaultFilterlnvocationSecurityMetadataSource获取要访问当前资源所需要的权限Collection<ConfigAttribute> 。

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

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

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

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.security.access;

import Java.util.Collection;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;

public interface AccessDecisionManager {
 /**
 *通过传递的参数来决定用户是否有访问对应受保护资源的权限
 */

    void decide(Authentication var1, Object var2, Collection<ConfigAttribute> var3) throws AccessDeniedException, InsufficientAuthenticationException;

    boolean supports(ConfigAttribute var1);

    boolean supports(Class<?> var1);
}

这里着重说明一下decide的参数:

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

object :要访问的受保护资源,web请求对应Fi足revocation

configAttributes :是受保护资源的访问策略,通过SecurityMetadataSource获取。

decide接口就是用来鉴定当前用户是否有访问对应受保护资源的权限。

授权决策

AccessDecisionManager采用投票的方式来确定是否能够访问受保护资源。

AccessDecisionManager中包含的一系列AccessDecisionVoter将会被用来对Authentication是否有权访问受保护对象进行投票,AccessDecisionManager根据投票结果,做出最终决策。

AccessDecisionVoter是一个接口 ,其中定义有三个方法,具体结构如下所示。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.security.access;

import java.util.Collection;
import org.springframework.security.core.Authentication;

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_ABS7AIN表示弃权

如果一个AccessDecisionVoter不能判定当前 Authentication是否拥有访问对应受保护对象的权限,则其vote()方法的返回值应当为弃权ACCESS_ABSTAIN。

Spring Security内置了三个基于投票的AccessDecisionManager实现类,它们分别是 AffirmativeBased、ConsensusBased和UnanimousBased。

AffirmativeBased的逻辑是:

  • 只要有AccessDecisionVoter的投票为ACCESS_GRANTED则同意用户进行访问;
  • 如果全部弃权也表示鮑;
  • 如果没有一个人投赞成票,但是有人投反对票,则将抛出AccessDeniedException,, Spring security默认使用的是AffirmativeBased。

ConsensusBased的逻辑是:

  • 如果赞成票多于反对票则表示通过。
  • 反过来,如果反对票多于赞成票则将抛出AccessDeniedException,,
  • 如果赞成票与反对票相同且不等于0 ,并且属性allowlfEqualGrantedDeniedDecisions的值为true,则表示通过,否则将抛出异常AccessDeniedException。参数allowlfEqualGrantedDeniedDecisions的值默认为true。
  • 如果所有的AccessDecisionVoter都弃权了,则将视参数allowlfAIIAbstainDecisions的值而定,如果该值为true则表示通过,否则将抛出异常AccessDeniedExceptiono。参数allowlfAIIAbstainDecisions的值默认为false。

UnanimousBased

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

UnanimousBased的逻辑具体来说是这样的:

  • 如果受保护对象配置的某一个ConfigAttribute被任意的AccessDecisionVoter反对了,则将抛出 AccessDeniedExceptiono
  • 如果没有反对票,但是有赞成票,则表示通过。
  • 如果全部弃权了,则将视参数allowlfAIIAbstainDecisions的值而定,true则通过,false则抛出 AccessDeniedExceptiono SpringSecurity也内置一些投票者实现类如RoleVoter、AuthenticatedVoter和WebExpressionVoter等,可以自行查阅资料进行学习。


原文始发于微信公众号(步尔斯特):【微服务|Spring Security⑭】spring security授权流程

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/48005.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!