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备…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...

排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...