spring security 中的授权使用
一、认证
身份认证,就是判断一个用户是否为合法用户的处理过程。Spring Security 中支持多种不同方式的认证,但是无论开发者使用那种方式认证,都不会影响授权功能使用。因为 SpringSecurity 很好做到了认证和授权解耦。
二、授权
授权,即访问控制,控制谁能访问哪些资源。简单的理解授权就是根据系统提前设置好的规则,给用户分配可以访问某一个资源的权限,用户根据自己所具有权限,去执行相应操作。
2.1权限管理核心概念
我们得知认证成功之后会将当前登录用户信息保存到Authentication 对象中,Authentication 对象中有一个getAuthorities() 方法,用来返回当前登录用户具备的权限信息,也就是当前用户具有权限信息。该方法的返回值为 Collection<?extends GrantedAuthorit,当需要进行权限判断时,就回根据集合返回权限信息调用相应方法进行判断。
2.2 GrantedAuthority 解释
那么问题来了,针对于这个返回值 GrantedAuthority 应该如何理解呢? 是角色还是权限?
我们针对于授权可以是 基于角色权限管理 和 基于资源权限管理 ,从设计层面上来说,角色和权限是两个完全不同的东西: 权限是一些具体操作,角色则是某些权限集合。如:READ_BOOK 和 ROLE_ADMIN 是完全不同的。因此至于返回值是什么取决于你的业务设计情况:。基于角色权限设计就是: 用户 => 角色 => 资源 三者关系 返回就是用户的 角色。基于资源权限设计就是:用户e=>双限<=>资源”三者关系 返回就是用户的 权限。基于角色和资源权限设计就是: 用户角色<>权限<>资源 返回统称为用户的 权限为什么可以统称为权限,因为从代码层面角色和权限没有太大不同都是权限,特别是在Spring Security中,角色和权限处理方式基本上都是一样的。唯一区别 SpringSecurity在很多时候会自动给角色添加一个 ROLE_前缀,而权限则不会自动添加。
2.3 权限管理策略
Spring Security 中提供的权限管理策略主要有两种类型:
1)、基于过滤器(URL)的权限管理(FilterSecurityinterceptor)
基于过滤器的权限管理主要是用来拦截 HTTP 请求,拦截下来之后,根据 HTTP 请求地址进行权限校验。
2)、基于AOP 的权限管理 (MethodSecurityinterceptor)
基于AOP 权限管理主要是用来处理方法级别的权限问题。当需要调用某一个方法时,通过AOP 将操作拦截下来,然后判断用户是否具备相关的权限。
2.3.1 基于URL 权限管理
在配置中写死,/** 需要有xx角色或者权限才能访问
2.3.1.1 准备工作
1)pom.xml 依赖包
2)测试controller
3)security 配置
我们在controller中创建了三个方法,分别为
/adminInf 这个url(可以匹配 /adminInf. /adminInf/ /adminInf.htm 等等)需要拥有admin的角色才能访问
/rootInf 这个url 需要拥有root的角色才能访问
/getUser 这个url 需要拥有read:user的权限才能才能访问
2.3.1.2 security 配置
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {/*** 定义自己的userDetail**/@Beanpublic UserDetailsService userDetailsService() {InMemoryUserDetailsManager im = new InMemoryUserDetailsManager();im.createUser(User.withUsername("admin").password("{noop}123").roles("admin","root").build());im.createUser(User.withUsername("root").password("{noop}123").roles("root").build());im.createUser(User.withUsername("test").password("{noop}123").authorities("read:user").build());return im;}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService());}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().mvcMatchers("/adminInf").hasRole("admin") // /adminInf 这个url下面必须有 admin的角色才能访问.mvcMatchers("/rootInf").hasAnyRole("admin","root") // /rootInf 这个url下面 有 admin 或者root 角色均可以访问.mvcMatchers("/getUser").hasAnyAuthority("read:user") // /getUser 这个url 下面必须有 read:user 这个权限才能访问.anyRequest().authenticated().and().formLogin()// 开启form表单登录.and().csrf().disable();}
}
2.3.1.3 测试controller
@RestController
public class HelloController {@GetMapping("/getUser")public String getUser() {return "userinfo authority ok ";}@GetMapping("/adminInf")public String admin() {return "admin role ok ";}@GetMapping("/rootInf")public String root() {return "root role ok ";}
}
2.3.1.4 测试结果
1)、当我们登录admin 的用户时候访问,因为getUser没有配置权限,所以不能访问



2)、当我们登录test 的用户时候访问,因为rootinfo/ adminInfo没有配置角色,所以不能访问



2.3.1.5 基于多种匹配规则
MvcMatchersAuthorizedUrl 、mvcMatchers 基于mvc 的匹配规则
/test 可以匹配 /test. /test/ /test.h... 多种
org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry#antMatchers(java.lang.String...)
.antMatchers() 早期 4.0 之前使用,基于全路径匹配
/test 只能匹配 /test 这个路径下的方法
从用法上来看两个使用基本没有区别,区别主要是在于匹配的路径上,mvc 可以匹配范围更广,ant 是全匹配
org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry#regexMatchers(java.lang.String...) 基于正则方案,当我们写一个正则表达式就可以

2.4 基于方法的权限管理
基于方法的权限管理主要是通过AOP 来实现的,Spring Security 中通过
MethodSecuritvInterceptor 来提供相关的实现。不同在于Filter Security interceptor 只是在请
求之前进行前置处理,MethodSecuritvinterceptor 除了前置处理之外还可以进行后置处理。
前置处理就是在请求之前判断是否具备相应的权限,后置处理则是对方法的执行结果进行二
次过滤。前置处理和后置处理分别对应了不同的实现类。
2.4.1 开启注解支持
@EnableGlobalMethodSecurity
1)、perPostEnabled: 开启 Spring Security 提供的四个权限注解,@PostAuthorize
@PostFilter、@PreAuthorize 以及 @PreFilter。
2)、securedEnabled: 开启 Spring Security 提供的 @Secured 注解支持,该注解不支持权限表达式
3)、jsr250Enabled:开启JSR-250 提供的注解,主要是@DenyAll、@PermitAll、@RolesAll 同
样这些注解也不支持权限表达式
# 以上注解含义如下:
- @PostAuthorize: 在日标方法执行之后进行权限校验。
- @PostFiter: 在目标方法执行之后对方法的返回结果进行过滤。
- @PreAuthorize: 在目标方法执行之前进行权限校验。
- @PreFiter: 在日标方法执行之前对方法参数进行过滤
- @secured: 访问目标方法必须具各相应的角色
- @DenyA11: 拒绝所有访问。
- @PermitA1l: 允许所有访问。
- @RolesAllowed: 访问目标方法必须具备相应的角色
这些基于方法的权限管理相关的注解,一般来说只要设置 prePostEnabled=true 就够用了
2.4.2 权限表达式

2.4.3 角色权限实战
1) :
/**
* 登录用户必须是 admin 而且角色必须是 ADMIN
* @return
*/
@PreAuthorize("hasRole('ADMIN') and authentication.name == 'admin'")
@RequestMapping("hello")
public String hello() {
return "hello";
}

2)、
/**
* 登录的用户名必须和传过来的用户名一致才能通过 spe 表达式
* @param username
* @return
*/
@PreAuthorize("authentication.name == #username")
@RequestMapping("username")
public String username(String username) {
return "hello:" + username;
}

3)、
/**
* 过滤 users 对象里面的属性 id % 2 的数据,保留 不能整除的
* users 必须是一个集合,否则没法过滤 filterObject 固定写法
* @param users
* @return
*/
@PreFilter(value = "filterObject.id % 2 != 0",filterTarget = "users")
@RequestMapping("users")
public String addUser(@RequestBody List<SecurityUser> users) {
System.out.println(users);
try {
String userStr = new ObjectMapper().writeValueAsString(users);
return userStr;
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return "null ";
}


4、
/**
* 后置过滤 当请求过来的 id值为1的时候,那么就返回,否则就不返回
* @param id
* @return
*/
@PostAuthorize(value = "returnObject.id ==1 ")
@RequestMapping("getUserId")
public SecurityUser getUserId(Integer id) {
return new SecurityUser(id,"lq");
}

5)
/**
* 保留 id % 2 ==0 的数据返回,用来对方法返回值进行过滤
* @return
*/
@PostFilter(value = "filterObject.id %2==0 ")
@RequestMapping("getAllUser")
public List<SecurityUser> getAllUser() {
List<SecurityUser> userList = new ArrayList<>();
IntStream.rangeClosed(0,10)
.forEach(index -> userList.add(new SecurityUser(index,"lq-"+index)));
return userList;
}

jsr250 使用比较少的,因为功能比较单一
/*** 只能判断角色,而且需要自己加前缀 ROLE_ 当前用户必须有 ADMIN 权限才能查看* @return*/
@Secured({"ROLE_ADMIN"})
@RequestMapping(value = "getUser1")
public SecurityUser getUser1() {return new SecurityUser(1,"lisi");
}/*** 判断用户有 ADMIN或者 ROOT 角色就可以访问* @return*/
@Secured({"ROLE_ADMIN","ROLE_ROOT"})
@RequestMapping(value = "getUser2")
public SecurityUser getUser2() {return new SecurityUser(1,"王五");
}/*** 所有的用户都可以访问* @return*/
@PermitAll
@RequestMapping(value = "permitAll")
public String perAll() {return "permitAll ok ";
}/*** 所有的用户都拒绝访问* @return*/
@DenyAll
@RequestMapping(value = "denyAll")
public String denyAll() {return "denyAll ok ";
}/*** 判断用户有 ADMIN或者 ROOT 角色就可以访问* @return*/
@RolesAllowed({"ROLE_ADMIN","ROLE_ROOT"})
@RequestMapping(value = "rolesAllowed")
public String rolesAllowed() {return "rolesAllowed ok ";
}
三、授权原理分析
3.1 AccessDecisionManager
(访问决策管理器),用来决定此次访问是否被允许

3.2 AccessDecisionVoter
(访问决定投票器),投票器会检查用户是否具备应有的角色,进而投出赞成、反对或者弃权票。
AccesDecisionVoter和AccessDecisionManager 都有众多的实现类,在 AccessDecisionManager 中会换个遍历 AccessDecisionVoter,进而决定是否允许用户访问,因而 AaccesDecisionVoter 和 AccessDecisionManager 两者的关系类似于 AuthenticationProvider 和ProviderManager 的关系。
3.3 ConfigAttribute
用来保存授权时的角色信息

在 Spring Security 中,用户请求一个资源(通常是一个接口或者一个 Java 方法)需要的角色会被封装成一个 ConfigAttribute 对象,在configAttribute 中只有一个 getAttribute方法,该方法返回一个 Strng 字符串,就是角色的名称。一般来说,角色名称都带有一个 ROLE_前缀,投票器 AccessDecisionVoter 所做的事情,其实就是比较用户所具各的角色和请求某个资源所需的 ConfigAtuibute 之间的关系。
3.4 核心类 FilterSecurityInterceptor

3.4.1 源码
org.springframework.security.web.access.intercept.FilterSecurityInterceptor
org.springframework.security.web.access.intercept.FilterSecurityInterceptor#invoke
org.springframework.security.access.intercept.AbstractSecurityInterceptor#beforeInvocation
org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource#getAttributes
org. springframework.security.access.intercept.AbstractSecurityInterceptor#attemptAuthorization

3.4.2 SecurityMetadataSource
后期可以实现这个类,自定义过滤规则,我们下一章讲解动态从数据库如何配置,以及重写这个类的实现


四、我们自己的角色如何放进去
我们通过参考
org.springframework.security.core.userdetails.User 类中的roles方法

4.1 代码实现
// 获取权限信息 todo:后期从数据库查询
List<String>perList=Arrays.asList("new:query", "news:delete");
#角色 我们将这两个角色加上前缀
List<String>roles=Arrays.asList("ADMIN","USER");
List<String>roleList=roles.stream().map(r ->"ROLE_"+ r).collect(Collectors.toList());
perList.addAll(roleList);
LoginSessionUserInf loginSessionUserInf=new LoginSessionUserInf(tUserInf, perList);

相关文章:
spring security 中的授权使用
一、认证 身份认证,就是判断一个用户是否为合法用户的处理过程。Spring Security 中支持多种不同方式的认证,但是无论开发者使用那种方式认证,都不会影响授权功能使用。因为 SpringSecurity 很好做到了认证和授权解耦。 二、授权 授权&#x…...
python安装以及访问openAI API
安装python 我是python小白,所以需要一步一步来,先安装。 一口吃不成胖子,记住。 从官网下载python,目前最新版本是3.12,但是据说稳定版3.11更好一点,所以,下载3.11,注意不要下载…...
【Unity小技巧】URP管线遮挡高亮效果
前言 在URP渲染管线环境下实现物体遮挡高亮显示效果,效果如下:Unity URP遮挡高亮 实现步骤 创建层级,为需要显示高亮效果的物体添加层级,比如Player 创建一个材质球,也就是高亮效果显示的材质球找到Universal Render…...
C#中的GDI和GDI+(Graphics Device Interface Plus)图形设备接口
GDI的概念 GDI(Graphics Device Interface)是微软Windows操作系统中的一个组件,它提供了一组API,用于在显示器或打印机等图形设备上进行图形绘制和图像处理。GDI 是 Windows 编程中用于二维图形和图像处理的接口。 GDI 的主要功…...
谷粒商城のNginx
文章目录 前言一、Nginx1、安装Nginx2、相关配置2.1、配置host2.2、配置Nginx2.3、配置网关 前言 本篇重点介绍项目中的Nginx配置。 一、Nginx 1、安装Nginx 首先需要在本地虚拟机执行: mkdir -p /mydata/nginx/html /mydata/nginx/logs /mydata/nginx/conf在项目…...
Debug-027-el-tooltip组件的使用及注意事项
前言: 这两天,碰到这个饿了么的el-tooltip比较多。这个组件使用起来也挺简单的,常用于展示鼠标 hover 时的提示信息。但是有一些小点需要注意。这里不再机械化的介绍文档,不熟悉的话可以先看一下: https://element-pl…...
猫眼电影字体破解(图片转码方法)
问题 随便拿一篇电影做样例。我们发现猫眼的页面数据在预览窗口中全是小方框。在当我们拿到源码以后,数据全是加密后的。所以我们需要想办法破解加密,拿到数据。 破解过程 1.源码获取问题与破解 分析 在我们刚刚请求url的时候是可以得到数据的ÿ…...
flink wordcount
Maven配置pom文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/P…...
组合模式(Composite Pattern)
使用组合模式(Composite Pattern)是一个更优雅的方式来表示菜单和菜单项。组合模式允许我们将单个对象(如菜单项)和组合对象(如菜单)以相同的方式处理。 解决方案: 创建组合结构:我…...
教你制作一本加密的样本册
在这个信息的时代,保护自己的隐私和知识产权变得尤为重要。你有没有想过,如何将自己珍贵的样本资料变成一本只有自己才能查看的加密宝典?今天,我就来教你制作一本加密的样本册 第一步,打开浏览器,搜索FLBOO…...
C语言进阶【1】--字符函数和字符串函数【1】
本章概述 字符分类函数字符转换函数strlen的使用和模拟实现strcpy的使用和模拟实现strcat的使用和模拟实现strcmp的使用和模拟实现彩蛋时刻!!! 字符分类函数 字符: 这个概念,我们在以前的文章中讲过了。我们键盘输入的…...
git提交自动带上 Signed-off-by信息
为了确保在使用 Signed-off-by 签名的同时保留你的提交消息,你需要修改 prepare-commit-msg 钩子脚本,以便它不会丢失原始的提交信息。 增加prepare-commit-msg 钩子以保留提交消息 prepare-commit-msg 钩子的目的是在提交信息文件中插入额外的内容&am…...
图论(2)
一、度 度统计的是一个节点上又多少条边 度出度入度 出度:统计以该节点为起始点箭头指向外面的边的条数 入度:统计箭头指向该节点的边数 度为1的节点为悬挂节点,边为悬挂边 用矩阵计算节点的度 二、握手定理 比如这里第一个集合里面有三…...
ASP.NET Core 入门教学十九 依赖注入ioc
ASP.NET Core内置了对依赖注入(Dependency Injection,简称DI)的支持,这是一种设计模式,用于实现控制反转(Inversion of Control,简称IoC),从而使得应用程序组件之间的耦合…...
omm kill 内存碎片化
内存频繁 OOM(Out of Memory)会导致内存碎片化,并进一步加剧无可用内存分配的问题。碎片化是内存管理中常见的问题,当系统频繁分配和释放内存时,内存空间会被分割成许多小块,虽然内存总量可能足够,但这些小块无法满足较大进程或数据的内存需求,最终导致系统无法找到足够…...
JS中给元素添加事件监听器的各种方法详解(包含比较和应用场景)
JavaScript 中给元素添加事件监听器的各种方法详解 在 JavaScript 中,事件处理是前端开发的一个重要部分。无论是点击按钮、提交表单,还是鼠标悬停,都涉及到事件监听。本文中,我将详细讲解各种给元素添加事件监听器的方法&#x…...
Python基本数据类型之复数complex
来源: “码农不会写诗”公众号 链接:Python基本数据类型之复数complex 文章目录 01 基本概念02 基本运算03 拓展1复数与向量 复数complex Python基本数据之复数(complex)即包含实部和虚部的数字。 01 基本概念 即包含实部和虚部的数字。 在Python中&am…...
第六届机器人与智能制造技术国际会议 (ISRIMT 2024)
目录 会议详情 主题 会议官网 会议详情 第六届机器人与智能制造技术国际研讨会(ISRIMT 2024)计划于2024年9月20-22日在常州举行。会议主要聚焦“机器人”和“智能制造技术”的研究领域,旨在为机器人和智能制造技术领域的专家学者、工程技术…...
鸿蒙轻内核M核源码分析系列十九 Musl LibC
往期知识点记录: 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总 轻内核M核源码分析系列一 数据结构-双向循环链表 轻内核M核源码分析系列二 数据结构-任务就绪队列 鸿蒙轻内核M核源码分析系列三 数据结构-任务排序链表 轻…...
mysqldump备份恢复数据库
mysqldump程序可以用来备份和恢复数据库 ,默认情况mysqldump会创建drop table, create table,和insert into的sql语句. 语法 > mysqldump [options] db_name [tbl_name ...] > mysqldump [options] --databases db_name ... > mysqldump [options] --all-databases备…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...

