看源码,重新审视Spring Security中的角色(roles)是怎么回事
在网上看见不少的博客、技术文章,发现大家对于Spring Security中的角色(roles)存在较大的误解,最大的误解就是没有搞清楚其中角色和权限的差别(好多人在学习Spring Security时,是不是对于到底加不加“ROLE_”前缀有点犯蒙),有时候觉得在进行权限控制时用权限名称或者用角色名称都差不多(大家这种感觉是对的,如果简单应用确实差不太多)。
我们在进行角色权限控制设计时,一般包括账户(users)、角色(roles)、权限(authorities)这三部分。
1)一个账户一般对应一个或多个角色;
2)一个角色对应多个权限(authorities),反过来一个权限也对应多个角色;
3)账户只和角色关联,通过角色,间接和权限产生关系;
4)角色不是固定死的,是能够动态创建的,每个角色具有的权限能够灵活的进行调整;
5)在系统完成详细设计后,有哪些权限就已经确定下来,权限的层级结构和数量、与账户和角色没半点关系。
基于以上的说明,我们从源码的角度来说明Spring Security的账户、角色和权限是怎么一回事。
Spring Security工作流程:通过登录的账户,找到该账户对应的角色/权限,并把自定义的权限集合转换为Spring Security认可的权限集合List<GrantedAuthority>,然后结合自定义的账号、密码,和新权限集合这三个参数,创建一个Spring Security认可的账号实例,再然后根据自定义的鉴权规则,进行权限控制。
这里面如何创建账号、角色、权限,实现用户认证、进行鉴权的细节就不讲了,因为这个不是本篇文章的重点,有兴趣的读者可以看我的视频介绍:https://edu.51cto.com/sd/091c7 ,里面有详细的如何进行实战型的Spring Security角色权限控制模块的开发。
重点来了,通过应用角色权限控制的应用,看Spring Security如何利用角色和权限的
四种鉴权的方式:
hasRole(String role)
hasAnyRole(String... roles)
hasAuthority(String authority)
hasAnyAuthority(String... authorities)
在源码类SecurityExpressionRoot.java中,我们看看这四种方式的实现形式:

大家从上面的图看出什么端倪没有?
hasRole(String role) --》 hasAnyRole(String... roles) --》hasAnyAuthorityName
hasAuthority(String authority) --》hasAnyAuthority(String... authorities) --》hasAnyAuthorityName
不管是基于角色,还是基于权限,最后鉴权都落实到hasAnyAuthorityName这个方法上。
follow me,我们继续往下刨根,看看hasAnyAuthorityName这个方法里面有些什么,注意上面代码中的调用hasAnyAuthorityName时,传递的参数,一个是

另外一个是

对应的都是一个实现方法。
从hasAnyAuthorityName这个方法中,我们可以知道,这是把传进去的一个或多个角色/权限,在登录用户具有的权限中进行查找

这里面的大家看到了吧,角色和权限是混合在一起进行鉴权的(题外话,大家看大神们写的代码,注意到其中的var5、var6、var4,这是搞什么?严重不符合命名规范啊)。
那么Spring Security是如何区分集合中的是权限、还是角色呢,我们继续抽丝剥茧,看看该方法中的getRoleWithDefaultPrefix(prefix, role)方法。


看上面的代码清晰明了了吧,说明如下:
如果传进去的角色名称/权限名称为null,直接返回null;
如果传进去的角色名称/权限名称不为null,则判断defaultRolePrefix前缀这个参数是否为空和其长度,如果不为空,且长度不为0,则传进的参数为角色名称,那么继续判断其是否是以“ROLE”开始,如果不是,则在名称前添加前缀“ROLE”,并返回新的名称;
如果不是以上情况,即参数是权限名称或者带有“ROLE_”前缀的角色名称,直接返回传进去的字符串参数。
看了以上的部分源码解析,我们可以得出什么结论呢(以角色、权限存放在数据库为例):
1、原生的角色和权限并没有本质的区别,在鉴权时走的是完全相同的一个通道;
2、在进行权限控制时,角色可加可不加“ROLE”前缀,但在数据库中定义时,角色名称一定要添加“ROLE”前缀;
3、角色与权限之间并没有建立映射关系,角色是角色、权限是权限,这与我们实际应用中对角色的要求有很大出入;
4、实际应用中的角色被固化到代码中,也与实际要求不符,实际应用中,权限作为子节点可以写死,而角色作为全部或者部分权限的集合应该可以灵活调整;
5、不管是角色鉴权,还是权限鉴权,都只是以角色/权限的名称作为判断依据,所以权限的名称要唯一。
另外,从Spring Security的源码分析中可以发现,我们还可以通过RoleHierarchy进行角色的继承(默认admin登录只能访问/admin,访问不了/user;而user登录只能访问/user),但在实际项目中,最主要强调的是角色的灵活性,而不是继承性。
所以,对角色的管理、角色和权限的映射关系,都需要我们自己来实现。
好了,对Spring Security角色(roles)的分析就到此结束,从以上分析看,我们如果要把Spring Security应用于实际项目中,还需要做不少工作,至于如何简洁高效的利用Spring Security进行角色权限控制模块的开发,有兴趣的读者可以参见视频:https://edu.51cto.com/sd/091c7 ,希望对大家有有所帮助。
看源码,重新审视Spring Security中的角色(roles)是怎么回事的更多相关文章
- 五:Spring Security 中的角色继承问题
Spring Security 中的角色继承问题 以前的写法 现在的写法 源码分析 SpringSecurity 在角色继承上有两种不同的写法,在 Spring Boot2.0.8(对应 Spring ...
- 专治不会看源码的毛病--spring源码解析AOP篇
昨天有个大牛说我啰嗦,眼光比较细碎,看不到重点.太他爷爷的有道理了!要说看人品,还是女孩子强一些.原来记得看到一个男孩子的抱怨,说怎么两人刚刚开始在一起,女孩子在心里就已经和他过完了一辈子.哥哥们,不 ...
- 【spring源码学习】spring事务中的嵌套事务中的保存点相关知识
JDBC事务保存点(setSavepoint, releaseSavepoint )实例 以下是使用事务教程中描述的setSavepoint和回滚的代码示例. 此示例代码是基于前面章节中完成的环境和数 ...
- Spring AOP源码解析——专治你不会看源码的坏毛病!
昨天有个大牛说我啰嗦,眼光比较细碎,看不到重点.太他爷爷的有道理了!要说看人品,还是女孩子强一些. 原来记得看到一个男孩子的抱怨,说怎么两人刚刚开始在一起,女孩子在心里就已经和他过完了一辈子.哥哥们, ...
- 【源码讲解】Spring事务是如何应用到你的业务场景中的?
初衷 日常开发中经常用到@Transaction注解,那你知道它是怎么应用到你的业务代码中的吗?本篇文章将从以下两个方面阐述Spring事务实现原理: 解析并加载事务配置:本质上是解析xml文件将标签 ...
- 带着萌新看springboot源码8(spring ioc源码上)
emmm.....这次先不说springboot原理,先好好回顾一下以前的注解版spring原理,先把spring原理了解清晰了,再看springboot原理更容易. 要说起spring,最重要的就是 ...
- FastJson遇见的问题或项目实战中优化的问题,看源码都可以解决
1:感觉见鬼了一般存储JSONObject中的字段竟然不见了? JSONObject object=new JSONObject(); Map fields = new HashMap(); fiel ...
- python3-开发进阶 django-rest framework 中的 版本操作(看源码解说)
今天我们来说一说rest framework 中的 版本 操作的详解 首先我们先回顾一下 rest framework的流程: 请求进来走view ,然后view调用视图的dispath函数 为了演示 ...
- 结合源码浅谈Spring容器与其子容器Spring MVC 冲突问题
容器是整个Spring 框架的核心思想,用来管理Bean的整个生命周期. 一个项目中引入Spring和SpringMVC这两个框架,Spring是父容器,SpringMVC是其子容器,子容器可以看见父 ...
随机推荐
- Java实现蓝桥杯VIP 算法训练 P0502
试题 算法训练 P0502 资源限制 时间限制:1.0s 内存限制:256.0MB 编写一个程序,读入一组整数,这组整数是按照从小到大的顺序排列的,它们的个数N也是由用户输入的,最多不会超过20.然后 ...
- Java实现 LeetCode 119 杨辉三角 II
119. 杨辉三角 II 给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行. 在杨辉三角中,每个数是它左上方和右上方的数的和. 示例: 输入: 3 输出: [1,3,3,1] 进阶: ...
- Java实现 蓝桥杯VIP 算法提高 三角形面积
算法提高 三角形面积 时间限制:1.0s 内存限制:256.0MB 问题描述 由三角形的三边长,求其面积. 提示:由三角形的三边a,b,c求面积可以用如下的公式: s=(a+b+c)/2 输入格式 由 ...
- Java 实现 蓝桥杯 生兔子问题
生兔子问题 有一对兔子,从出生后第四个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子.假如兔子都不死,计算第十个月兔子的总数? 分析: 四个月开始生兔子,则:F(N) = f(n-1) ...
- java实现顺时针螺旋填入
从键盘输入一个整数(1~20) 则以该数字为矩阵的大小,把 1,2,3-n*n 的数字按照顺时针螺旋的形式填入其中.例如: 输入数字 2,则程序输出: 1 2 4 3 输入数字 3,则程序输出: 1 ...
- java实现第六届蓝桥杯打印菱形
打印菱形 给出菱形的边长,在控制台上打印出一个菱形来. 为了便于比对空格,我们把空格用句点代替. 当边长为8时,菱形为: .......* ......*.* .....*...* ....*.... ...
- 流程图(HTML5拖拽)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 如何在交互式环境中执行Python程序
相信接触过Python的小伙伴们都知道运行Python脚本程序的方式有多种,目前主要的方式有:交互式环境运行.命令行窗口运行.开发工具上运行等,其中在不同的操作平台上还互不相同.今天,小编讲些Pyth ...
- Jmeter(八) - 从入门到精通 - JMeter配置元件(详解教程)
1.简介 JMeter配置元件可以用来初始化默认值和变量,读取文件数据,设置公共请求参数,赋予变量值等,以便后续采样器使用.将在其作用域的初始化阶段处理.配置元件(Config Element)提供对 ...
- javascript 面向对象学习(一)——构造函数
最近在学习设计模式,找了很多资料也没有看懂,看到怀疑智商,怀疑人生,思来想去还是把锅甩到基础不够扎实上.虽然原型继承.闭包.构造函数也都有学习过,但理解得不够透彻,影响到后续提高.这次重新开始学习,一 ...