Spring Security权限管理原理

news2024/12/23 5:25:38

1.简介

授权是更具系统提前设置好的规则,给用户分配可以访问某一资源的权限,用户根据自己所具有的权限,去执行相应的操作,spring security提供的权限管理功能主要有两种:

  • 基于过滤器的权限管理功能(FilterSecurityInterceptor)
  • 基于AOP的权限管理功能(MethodSecurityInterceptor)

2. 核心概念

2.1 角色与权限

用户信息都保存在Authentication信息中,Authentication对象中有一个Collection<? extends GrantedAuthority> getAuthorities()  当需要进行鉴权时,就会调用该方法获取用户权限,进而做出判断。无论用户采取何种认证方式,都不影响授权。

从设计层面来讲,角色和权限是两个完全不同的东西,权限是一些具体操作,例如read、write,角色则是某些权限的集合,例如管理员、普通用户。

从代码层面讲,角色和权限并没有太大的不同。

至于Collection<? extends GrantedAuthority> getAuthorities() 的返回值,需要分情况对待:

(1) 如果权限系统设计的比较简单,用户<==>权限<==>资源三者之间的关系,那么getAuthorities就是返回用户的权限

(2) 如果权限系统设计的比较复杂,如用户<==>角色<==>权限<==>资源,此时将getAuthorities的返回值当作权限来理解。由于Spring Security并未提供相关的角色类,因此此时需要我们自定义角色类。

1

2

3

4

5

6

7

8

9

10

public class Role implements GrantedAuthority{

private String name;

private List<SimpleGrantedAuthority> allowedOperations=new ArrayList<>();

@Override

public String getAuthority{

 return name;

}

省略getter/setter方法

}

角色继承自GrantedAuthority,一个角色对应多个权限,然后在定义用户类的时候,将角色转为权限即可.

1

2

3

4

5

6

7

8

9

10

11

12

13

public class User implements UserDetails{

private List<Role> roles=new ArrayList<>();

@Override

public Collection<? extends GrantedAuthority> getAuthorities(){

List<SimpleGrantedAuthority> authorities=new ArrayList<>();

for(Role role:roles){

 authorities.addAll(role.getAllowedOperations());

}

return authorities.stream().distinct().collect(Collectors.toList());

}

省略getter/setter方法

}

2.2 角色继承

指角色存在一个上下级关系,例如ADMIN继承自USER,那么ADMIN就自动具备USER的所有权限。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

public interface RoleHierarchy {

    /**

     * 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 > ROLE_B > 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.

     */

    Collection<? extends GrantedAuthority> getReachableGrantedAuthorities(

            Collection<? extends GrantedAuthority> authorities);

}

2.3 FilterSecurityInterceptor处理器

基于过滤器的权限过滤器(FilterSecurityInterceptor)有一个前置过滤器和后置过滤器,首先由前置处理器判断发起当前请求的用户是否具备相应的权限,如果具备则请求继续向下走,到达目标方法并执行完毕。在相应时,会经过FilterSecurityInterceptor,次吃由后置处理器再去完成收尾工作(后置过滤器一般不工作),如图2-3所示。

图2-3

2.4 前置过滤器

前置过滤器主要有两个核心组件,分别是投票器和决策器。

2.4.1 投票器

当投票器在投票时,需要两方面的权限:其一是当前用户具备哪些权限;其二是当前访问的URL需要哪些权限才能访问,投票器就是对这两种权限进行比较。其接口如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

/**

 * Indicates a class is responsible for voting on authorization decisions.

 * <p>

 * 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}.

 *

 * @author Ben Alex

 */

public interface AccessDecisionVoter<S> {

    //同意

    int ACCESS_GRANTED = 1;

    //放弃

    int ACCESS_ABSTAIN = 0;

    //拒绝

    int ACCESS_DENIED = -1;

    //用来判断是否支持ConfigAttribute对象

    boolean supports(ConfigAttribute attribute);

    //用来判断是否支持受保护的安全对象

    boolean supports(Class<?> clazz);

    //具体投票方法,authentication可以提取出当前用户具备的权限;object表示受保护的安全对象,是一个FilterInvocation实例;attributes表示访问受保护对象所需的权限。返回值就是-1/0/1

  int vote(Authentication authentication, S object, Collection<ConfigAttribute> attributes);

}

AccessDecisionVoter常用的实现类如下图2-4-1所示,本项目中主要用到RoleVoter和RoleHierarchyVoter。

RoleVoter:RoleVoter是根据登陆主体的角色进行投票,即判断当前用户是否具备受保护对象所需要的角色。需要注意的是,默认情况下,角色需要以ROLE_开始,否则supports方法会直接返回false。

RoleHierarchyVoter:继承自RoleVoter,投票逻辑和RoleVoter一样,不同的是RoleHierarchyVoter支持角色的继承,它通过RoleHierarchyImpl对象对用户所具有的角色进行解析,获得用户真正可触达的角色,而RoleVoter则直接调用 authentication.getAuthorities()方法获得用户的角色。

图2-4-1

2.4.2 决策器

决策器由AccessDecisionManager负责,AccessDecisionManager会同时管理多个投票器,由AccessDecisionManager调用投票器进行投票,然后根据投票结果做出相应的决策。

1

2

3

4

5

6

7

8

9

public interface AccessDecisionManager {

    void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)

            throws AccessDeniedException, InsufficientAuthenticationException;

    boolean supports(ConfigAttribute attribute);

    boolean supports(Class<?> clazz);

}

decide方法:是核心的决策方法,在这个方法中判断是否允许当前URL调用, 如果拒绝访问的话会抛出AccessDeniedException异常。

supports(ConfigAttribute) 方法:用来判断是否支持ConfigAttribute对象。

supports(Class)方法:用来判断是否支持当前安全对象。

和决策器相关的类关系,如图2-4-2所示,AccessDecisionManager会同时管理多个投票器,由AccessDecisionManager调用投票器进行投票,然后根据投票结果做出相应的决策,有一个抽象实现类AbstractAccessDecisionManager,AbstractAccessDecisionManager一共有三个子类:
AffirmativeBased:一票通过机制(默认即此)
ConsensusBased:少数服从多数机制,平局的话,则看 allowIfEqualGrantedDeniedDecisions 参数的取值
UnanimousBased:一票否决制


 

图2-4-2

2.5 权限元数据

2.5.1 ConfigAttribute

在介绍投票器的时候,在具体的投票方法vote中,受保护的对象所需要的权限保存在一个Collection集合中,集合中的对象是ConfigAttribute而不是GrantedAuthority,ConfigAttribute用来存储与安全系统相关的配置属性,也就是系统关于权限的配置,接口如下:

1

2

3

public interface ConfigAttribute extends Serializable{

 String getAttribute();

}

 

只有一个getAttribute方法返回具体的权限字符串,而GrantedAuthority则是通过getAuthority方法返回用户所具有的权限,随着两个类不同,但是二者的返回值都是字符串是可以比较的。其部分实现类如图2-5-1所示。

图2-5-1

2.5.2 SecurityMetadataSource

提供受保护的对象所需的权限,例如,用户访问了一个URL地址需要哪些权限才能访问?这个就由SecurityMetadataSource提供

3. 基于URL地址的权限管理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/46647.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Syntax Error: Error: Missing binary. See message above.

安装完nvm&#xff0c;选择后node版本&#xff0c;在idea中引入vue项目&#xff0c;npm install后&#xff0c;运行npm run serve后 控制台出现下面错误&#xff1a; Try running this to fix the issue: D:\Program Files\nodejs\node.exe E:\vue-project\node_modules\fibe…

篮球竞赛预约平台设计与实现的源码+文档

摘 要 随着信息化时代的到来&#xff0c;管理系统都趋向于智能化、系统化&#xff0c;篮球竞赛预约平台也不例外&#xff0c;但目前国内仍都使用人工管理&#xff0c;市场规模越来越大&#xff0c;同时信息量也越来越庞大&#xff0c;人工管理显然已无法应对时代的变化&#x…

platform总线

1、什么是platform总线&#xff1f; platform是Linux内核抽象出来的软件代码&#xff0c;用于设备与驱动的连接&#xff0c;设备与驱动通过总线进行匹配&#xff1b;匹配成功后会执行驱动中的probe函数&#xff0c;在probe函数中可以获取到设备的信息&#xff1b; 设备与驱动…

gitlab的使用方法,详解gitlab操作

1.导读 本教程主要讲解了GitLab在项目的环境搭建和基本的使用&#xff0c;可以帮助大家在企业中能够自主搭建GitLab服务&#xff0c;并且可以GitLab中的组、权限、项目自主操作。 - GitLab简介 - GitLab环境搭建 - GitLab基本使用(组、权限、用户、项目) 2.GitLab简介 Gi…

debug - JLX12864C(ST7920-12864)液晶屏不能使用串行通讯的原因

文章目录debug - JLX12864C(ST7920-12864)液晶屏不能使用串行通讯的原因概述调试备注ENDdebug - JLX12864C(ST7920-12864)液晶屏不能使用串行通讯的原因 概述 正在给板子写出厂测试程序, 买的12864型号是JLX12864C. STC官方给的例程是并行通讯, 好使. 但是想在测试程序中改为…

Linux线程基础

目录 一&#xff0c;线程函数 1、创建一个线程 2、获取自身线程ID 3、线程终止 4、取消正在执行线程 5、线程等待 6、线程分离 二&#xff0c;线程的使用 1&#xff0c;线程等待和线程分离 (1)、线程等待 (2)、线程分离 (3)、线程等待线程分离同时进行 三&#xff…

中英翻译《森林火灾的预防措施》

The Preventive Measures for Forest Fire 森林火灾的预防措施 The preventive measures for forest fires include some preemptive methods that can help reduce the risks of fires and contril their severity and spread, and thus, maintain ecological balance …

vue与es6的知识点

var let const let const 不能重复声明&#xff0c;局部作用域&#xff0c; 案例 let name "未来"; let str 我是${name}; console.log(str); 箭头函数 let add (x)>{ return x; } console.log(add(9)) v-bind 绑定标签的属性 src class a titie等等…

Qt for Android实现开机自启动

前言 最近项目需要&#xff0c;在Android上编写的程序&#xff0c;需要实现开机自启动。笔者查询了下资料&#xff0c;基本原理如下&#xff1a; 当Android启动时&#xff0c;会发出一个系统广播&#xff0c;内容为ACTION_BOOT_COMPLETED&#xff0c;它的字符串常量表示为 an…

详解时间复杂度计算公式(附例题细致讲解过程)

这几天开始刷力扣上面的算法题&#xff0c;有些题目上面限制时间复杂度和空间复杂度&#xff0c;题目虽然写出来了&#xff0c;但是很没底。印象里数据结构老师讲过一点&#xff0c;沉睡的记忆苏醒了。只记得一个时间复杂度是O(n)&#xff0c;空间复杂度是S(n)。for循环常常是O…

中学语文教学参考杂志社中学语文教学参考编辑部2022年第27期目录

理论学术_课题荟萃《中学语文教学参考》投稿&#xff1a;cn7kantougao163.com 统编教材鲁迅作品的民俗文化分析及教学应用 张家波;张晓静; 3-5 高中语文线上学习的实践与反思 张灵贵; 6-797 不同课型导学案设计建议 张桂霞; 8-997 现代化进程中的阵痛:《哦,香雪…

遇到Bug漏测,不能总想着甩锅吧

背景 漏测Bug是指产品逻辑缺陷在测试过程中没有被发现&#xff08;尤其是测试环境可以重现的缺陷&#xff09;&#xff0c;上线版本发布后或者在用户使用体验后发现并反馈回来的缺陷。 漏测Bug可能造成线上故障或者资损&#xff0c;在对产品测试过程中&#xff0c;自己也难免…

Pandas常见筛选数据的五种方法其一逻辑筛选。看见必懂,懂者必会,会者必加分

前言&#xff1a;Pandas的数据操作中&#xff0c;最基本的就是操作的筛选了&#xff0c;但是对新学员来说的这又是一个难点&#xff0c;因为方法比较多&#xff0c;不容易记。在此总结一下pandas中的一些常用的数据筛选操作。 逻辑筛选数据&#xff1a;切片&#xff08;[ ]&am…

ubuntu 安装、配置FTP

ubuntu 安装、配置FTP 提示&#xff1a;ubuntu 16.0.4&#xff0c;不同版本操作可能稍有不同 前言 本文主要对服务器安装及配置FTP做一个记录&#xff0c;涉及安装、配置、创建FTP账号、以及第一次连接异常等。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可…

单载波频域均衡matlab仿真,包括卷积编码维特比译码,矩阵交织,QPSK调制解调,导频插入,MMSE-FDE频域均衡

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 频域均衡是从校正系统的频率特性出发&#xff0c;利用一个可调滤波器的频率的频率特性去补偿信道或系统的频率特性&#xff0c;使包括可调滤波器在内的基带系统的总特性接近无失真传输条件。频域…

【Spring项目中的Controller理解】

目录 1. 添加依赖 2. 关于异常 1. 添加依赖 首先&#xff0c;需要保障此项目中存在spring-boot-starter-web依赖项&#xff0c;否则&#xff0c;当前项目并不具备Web应用程序开发所需的依赖&#xff01; 提示&#xff1a;spring-boot-starter-web是建立在spring-boot-starte…

基于Python的Django开发接口框架搭建

1、安装Django&#xff0c;如图1 命令行执行&#xff1a;pip install django 2、创建Django项目&#xff0c;如图2 django-admin startproject imooc 3、创建Django的应用项目&#xff0c;如图3 必须进入项目文件下执行命令&#xff1a; python3 manage.py startapp app …

✿✿✿JavaScript ---- 函数/js内置对象

目 录 一、函数 自调用函数如下演示&#xff1a; 二、JS中的内置对象 2.Number对象 3.Date 对象 补&#xff1a;第三方的日期工具类 moment.js 4.Math对象 5.数组对象 补&#xff1a;ES6中数组对象新增的方法 6.Global全局方法对象 7.RegExp(**)正则表达式对象 一、…

Word2010入门

Word简介 Microsoft Office Word 2010是微软公司的一个文字处理应用程序。 我们可以利用Word编辑文字、图文排版、建立表格、图形绘制。一直以来&#xff0c;Word都是最流行的文字处理应用程序。 .doc、.docx是Word软件默认存储文件类型&#xff0c; .docx正在逐步取代.doc。…

QT和网络调试助手之间的UDP通信

文章目录一、背景二、实现过程简述UDP协议工作原理及编程模型UDP 接收端UDP 发送端运行UDP接收端和发送端运行UDP发送端发送数据给网络调试助手一、背景 之前一篇博客实现了两个网络调试助手之间的UDP通信。 文章链接&#xff1a;在MacOS上实现两个网络调试助手的UDP通信测试…