史上最简单的Spring Security教程(十九):AccessDecisionVoter简介及自定义访问权限投票器

news/2024/11/22 21:58:19/

 

为了后续对 AccessDecisionManager 的介绍,我们先来提前对 AccessDecisionVoter 做个简单的了解,然后,在捎带手自定义一个 AccessDecisionVoter

AccessDecisionVoter 的注释介绍如下:

Indicates a class is responsible for voting on authorization decisions. The coordination of voting (ie polling {@code AccessDecisionVoter}s, tallying their responses, and making the final authorization decision) is performed by an {@link org.springframework.security.access.AccessDecisionManager}.

什么意思呢?

翻译过来就是,AccessDecisionVoter 是一个投票器,负责对授权决策进行表决。然后,最终由唱票者AccessDecisionManager 统计所有的投票器表决后,来做最终的授权决策。

先来看几种常用的投票器。

 

WebExpressionVoter

 

最常用的,也是 Spring Security 框架默认 FilterSecurityInterceptor 实例中 AccessDecisionManager 默认的投票器 WebExpressionVoter。其实,就是对使用 http.authorizeRequests() 基于 Spring-EL进行控制权限的的授权决策类。

http.authorizeRequests().anyRequest().authenticated().antMatchers().permitAll().antMatchers().hasRole().antMatchers().hasAuthority()......

 

他还需要一个 ExpressionHandler,感兴趣的话,可以去看一下文章史上最简单的Spring Security教程(十七):FilterSecurityInterceptor默认初始化逻辑剖析里面有对 WebExpressionVoter  ExpressionHandler 的相关介绍。

 

 

AuthenticatedVoter


针对 ConfigAttribute#getAttribute() 中配置为 IS_AUTHENTICATED_FULLY、IS_AUTHENTICATED_REMEMBERED、IS_AUTHENTICATED_ANONYMOUSLY 权限标识时的授权决策。因此,其投票策略比较简单:

public int vote(Authentication authentication, Object object,Collection<ConfigAttribute> attributes) {int result = ACCESS_ABSTAIN;
​for (ConfigAttribute attribute : attributes) {if (this.supports(attribute)) {result = ACCESS_DENIED;
​if (IS_AUTHENTICATED_FULLY.equals(attribute.getAttribute())) {if (isFullyAuthenticated(authentication)) {return ACCESS_GRANTED;}}
​if (IS_AUTHENTICATED_REMEMBERED.equals(attribute.getAttribute())) {if (authenticationTrustResolver.isRememberMe(authentication)|| isFullyAuthenticated(authentication)) {return ACCESS_GRANTED;}}
​if (IS_AUTHENTICATED_ANONYMOUSLY.equals(attribute.getAttribute())) {if (authenticationTrustResolver.isAnonymous(authentication)|| isFullyAuthenticated(authentication)|| authenticationTrustResolver.isRememberMe(authentication)) {return ACCESS_GRANTED;}}}}
​return result;}
}

 

PreInvocationAuthorizationAdviceVoter

 

用于处理基于注解 @PreFilter 和 @PreAuthorize 生成的 PreInvocationAuthorizationAdvice,来处理授权决策的实现。还记得我们最早使用 @PreAuthorize 来进行权限控制的介绍吗?史上最简单的Spring Security教程(十二):@PreAuthorize注解实现权限控制。

public int vote(Authentication authentication, MethodInvocation method,Collection<ConfigAttribute> attributes) {
​// Find prefilter and preauth (or combined) attributes// if both null, abstain// else call advice with them
​PreInvocationAttribute preAttr = findPreInvocationAttribute(attributes);
​if (preAttr == null) {// No expression based metadata, so abstainreturn ACCESS_ABSTAIN;}
​boolean allowed = preAdvice.before(authentication, method, preAttr);
​return allowed ? ACCESS_GRANTED : ACCESS_DENIED;
}

 

RoleVoter

 

角色投票器。用于 ConfigAttribute#getAttribute() 中配置为角色的授权决策。其默认前缀为 ROLE_,可以自定义,也可以设置为空,直接使用角色标识进行判断。这就意味着,任何属性都可以使用该投票器投票,也就偏离了该投票器的本意,是不可取的。

public int vote(Authentication authentication, Object object,Collection<ConfigAttribute> attributes) {if (authentication == null) {return ACCESS_DENIED;}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 authorityfor (GrantedAuthority authority : authorities) {if (attribute.getAttribute().equals(authority.getAuthority())) {return ACCESS_GRANTED;}}}}
​return result;
}

 

注意,决策策略比较简单,用户只需拥有任一当前请求需要的角色即可,不必全部拥有

 

 

RoleHierarchyVoter

 

基于 RoleVoter,唯一的不同就是该投票器中的角色是附带上下级关系的。也就是说,角色A包含角色B,角色B包含 角色C,此时,如果用户拥有角色A,那么理论上可以同时拥有角色B、角色C的全部资源访问权限。

/*** Returns an array of all reachable authorities.* <p>* Reachable authorities are the directly assigned authorities plus all authorities* that are (transitively) reachable from them in the role hierarchy.* <p>* Example:<br>* Role hierarchy: ROLE_A &gt; ROLE_B and ROLE_B &gt; ROLE_C.<br>* Directly assigned authority: ROLE_A.<br>* Reachable authorities: ROLE_A, ROLE_B, ROLE_C.** @param authorities - List of the directly assigned authorities.* @return List of all reachable authorities given the assigned authorities.*/
public Collection<? extends GrantedAuthority> getReachableGrantedAuthorities(Collection<? extends GrantedAuthority> authorities);

 

注意,同 RoleVoter 的决策策略,用户只需拥有任一当前请求需要的角色即可,不必全部拥有

以上就是常用的投票器,接下来,我们自定义一个投票器,与 RoleVoter 策略正好相反,必须拥有当前请求所需的全部角色才能访问。尝试一下。

@Override
public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {if (authentication == null) {return ACCESS_DENIED;}
​int result = ACCESS_ABSTAIN;Collection<? extends GrantedAuthority> authorities = extractAuthorities(authentication);
​for (ConfigAttribute attribute : attributes) {if (this.supports(attribute)) {result = ACCESS_DENIED;
​// Attempt to find all matching granted authorityfor (GrantedAuthority authority : authorities) {if (attribute.getAttribute().equals(authority.getAuthority())) {result = ACCESS_GRANTED;break;}}
​if (result == ACCESS_DENIED) {return ACCESS_DENIED;}}}
​return result;
}

 

其它逻辑包括 rolePrefix、supports等,与 RoleVoter完全一致,只修改决策部分的逻辑:只要当前请求所需任一角色不在用户拥有的角色范围内,即代表没有授权,拒绝访问。

其它详细源码,请参考文末源码链接,可自行下载后阅读。

 

 

源码


github

 

https://github.com/liuminglei/SpringSecurityLearning/tree/master/19

 

gitee

 

https://gitee.com/xbd521/SpringSecurityLearning/tree/master/19

 

 


 

回复以下关键字,获取更多资源

 

SpringCloud进阶之路 | Java 基础 | 微服务 | JAVA WEB | JAVA 进阶 | JAVA 面试 | MK 精讲

 

 

 

 

笔者开通了个人微信公众号【银河架构师】,分享工作、生活过程中的心得体会,填坑指南,技术感悟等内容,会比博客提前更新,欢迎订阅。

技术资料领取方法:关注公众号,回复微服务,领取微服务相关电子书;回复MK精讲,领取MK精讲系列电子书;回复JAVA 进阶,领取JAVA进阶知识相关电子书;回复JAVA面试,领取JAVA面试相关电子书,回复JAVA WEB领取JAVA WEB相关电子书。

 


http://www.ppmy.cn/news/679472.html

相关文章

三种方法用Verilog实现多人表决器

module biaojue( a,b,c,d,e,f); input a,b,c,d,e; output f; reg f; reg[2:0] count1; initial count10; always(a,b,c,d,e) begin count1abcde; fcount1<3?0:1;//当人数在三人以下是输出1 end endmodule module biaojue5( input a,b,c,d,e, output f ); assign fa&b&…

76、基于STM32单片机车牌识别摄像头图像处理扫描设计(程序+原理图+PCB源文件+相关资料+参考PPT+元器件清单等)

单片机主芯片选择方案 方案一&#xff1a;AT89C51是美国ATMEL公司生产的低电压&#xff0c;高性能CMOS型8位单片机&#xff0c;器件采用ATMEL公司的高密度、非易失性存储技术生产&#xff0c;兼容标准MCS-51指令系统&#xff0c;片内置通用8位中央处理器(CPU)和Flash存储单元&a…

Power BI 如何实现时间切片器默认选择最新日期

目前Power BI暂不支持切片器选择动态的默认值的功能&#xff0c;只能通过在Power BI Desktop 中预先选择某个固定值的方式发布到Power BI Service来实现过滤器的默认值效果。这可 以满足部分的需求&#xff0c;但是对于时间这种实时变化的维度&#xff0c;客户肯定希望每次打开…

标签、类选择器及CSS命名规范

一、标签选择器(元素选择器) 使用HTML标签名称作为选择器&#xff0c;按标签名称分类&#xff0c;为页面中某一类标签指定统一的CSS样式。 基本语法格式&#xff1a; 标签名{属性1&#xff1a;属性值1&#xff1b;属性2&#xff1a;属性值2&#xff1b;属性3&#xff1a;属性…

机器学习(十二)-基于规则的分类器

原创不易&#xff0c;转载前请注明博主的链接地址&#xff1a;Blessy_Zhu https://blog.csdn.net/weixin_42555080 本次代码的环境&#xff1a; 运行平台&#xff1a; Windows Python版本&#xff1a; Python3.x IDE&#xff1a; PyCharm   一 算法简介 基于规则的分类器是使…

有没有微信相互投票群?

“你好&#xff0c;我需要投票&#xff0c;你可以帮我吗&#xff1f;” 相信很多人在需要投票的时候&#xff0c;会联系各个亲戚朋友同事&#xff0c;熟悉的会帮你&#xff0c;不熟悉的呢&#xff1f;会想&#xff0c;凭什么我要帮你啊&#xff01; 我们相互间&#xff0c;都是…

smartscreen筛选器阻止了这个不安全的下载

今天用IE从云盘下载PPT文件时&#xff0c;提示&#xff1a;smartscreen筛选器阻止了这个不安全的下载。 如下图&#xff1a; 真是让人反感。 解决方法&#xff1a; 打开ie浏览器&#xff0c;选择工具-》internet选项。 在弹出的对话框上选择“安全”-》internet-“自定义级别…

SwiftUI 前后端完成项目之会议和投票管理支持二维码扫描Vapor Combine WebSockets

实战需求 SwiftUI 前后端完成项目之会议和投票管理支持二维码扫描Vapor Combine WebSockets 本文价值与收获 看完本文后,您将能够作出下面的界面 项目介绍 Mamba项目允许用户托管或加入会话,并对故事进行投票。 登陆界面 添加计划 选择卡片 分享session