Spring Security 6.x 系列(6)—— 显式设置和修改登录态信息
一、前言
此篇是对上篇 Spring Security 6.x 系列(5)—— Servlet 认证体系结构介绍 中4.9章节显式调用SecurityContextRepository#saveContext
进行详解分析。
二、设置和修改登录态
2.1 登录态存储形式
使用Spring Security
框架,认证成功后的用户信息会放在Authentication
对象的Principal
中,
Authentication
对象又会被放入SecurityContext
中,而SecurityContext
存在这2个地方:
-
SecurityContextHolderStrategy
:线程级别的SecurityContext
持有策略。有全局共享、线程继承、线程隔离等几种获取上下文的方式(上文有过介绍)。 -
SecurityContextRepository
:持久化SecurityContext
,默认存入HttpServletRequest
和HttpSession
。
在代码中,我们要获取用户登录信息,可以通过SecurityContextHolder.getContext().getAuthentication()
的方式获取,这种方式是从SecurityContextHolderStrategy
获取用户数据。而SecurityContextHolderStrategy
初始化数据又是来自SecurityContextRepository
,相关逻辑是在SecurityContextHolderFilter
类里。
SecurityContextHolderFilter#doFilter
源码如下:
查看securityContextRepository
如下:
设想一种场景,在用户登录后,编辑了用户信息,这时要同步刷新SecurityContext
里的用户信息。我们要如何更新这两个处的用户数据呢?
2.2 更新SecurityContextHolderStrategy中的用户信息
要更新SecurityContextHolderStrategy
非常简单,因为它保存在内存里,只要通过SecurityContextHolder.getContext().getAuthentication()
获取认证信息后,直接设置对应的属性,内存中属性值发生变化,后续处理逻辑就能读到最新值。
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
MyUser myUser = (MyUser) authentication.getPrincipal();
myUser.setNickname("新的昵称");
2.3 更新SecurityContextRepository中的用户信息
2.3.1 了解SecurityContextRepository接口
SecurityContextRepository
是一个接口,源码如下:
public interface SecurityContextRepository {/** @deprecated */@DeprecatedSecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder);default DeferredSecurityContext loadDeferredContext(HttpServletRequest request) {Supplier<SecurityContext> supplier = () -> {return this.loadContext(new HttpRequestResponseHolder(request, (HttpServletResponse)null));};return new SupplierDeferredSecurityContext(SingletonSupplier.of(supplier), SecurityContextHolder.getContextHolderStrategy());}void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response);boolean containsContext(HttpServletRequest request);
}
SecurityContextRepository
接口有以下几个实现类:
- NullSecurityContextRepository:什么都不做,也就是不会存储,每次请求都需要重新认证
- HttpSessionSecurityContextRepository:将
SecurityContext
保存在Session
中,获取的时候,从Session
中查询 - RequestAttributeSecurityContextRepository:将
SecurityContext
保存在请求对象HttpServletRequest
中 - DelegatingSecurityContextRepository:委派代理存储,内部维护多个
SecurityContextRepository
,实现同时支持多种方式存储SecurityContext
。
2.3.2 无法直接获取SecurityContextRepository对象
要知道怎么更新SecurityContextRepository
,我们先看其他地方是怎么调用它。往SecurityContextRepository
写数据是在用户认证成功之后,调用AbstractAuthenticationProcessingFilter#successfulAuthentication()
方法,执行认证成功的后续逻辑时。
这里的this.securityContextRepository
是通过setter
方法传进来的,并且发现Spring Security
没有把SecurityContextRepository
注册到Spring
容器,而且Spring Security
其他持有SecurityContextRepository
对象的类都没有暴露SecurityContextRepository
的获取方法。也就是说,我们无法从Spring Security
拿到默认的SecurityContextRepository
对象。
debug
发现this.securityContextRepository
属性指向了 DelegatingSecurityContextRepository
,这是委派代理存储,代理的对象是 RequestAttributeSecurityContextRepository
和 HttpSessionSecurityContextRepository
,所以在默认的情况下,用户登录成功之后,在这里就把登录用户数据分别存入到HttpSessionSecurityContextRepository
和RequestAttributeSecurityContextRepository
中。
部分DelegatingSecurityContextRepository
源码如下:
2.3.3 手动设置SecurityContextRepository对象
为了顺利拿到SecurityContextRepository
对象,我们可以手动往Spring
容器注册一个SecurityContextRepository
对象,然后把它塞到Spring Security
里。通过这种方式,我们能从Spring
容器拿到SecurityContextRepository
对象,然后随时刷新SecurityContext
。
具体实现代码如下:
@Bean
public SecurityContextRepository securityContextRepository() {return new DelegatingSecurityContextRepository(new RequestAttributeSecurityContextRepository(), new HttpSessionSecurityContextRepository());
}@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity, SecurityContextRepository securityContextRepository) throws Exception {httpSecurity.securityContext((context) -> context.securityContextRepository(securityContextRepository()));
}
这里DelegatingSecurityContextRepository
是Spring Security
中的SecurityContextRepository
默认实现,我们原封不动保留下来。
2.3.4 更新登录态
在更新完SecurityContextHolderStrategy
对象之后,我们显式把SecurityContext
重新保存到SecurityContextRepository
。
// 更新SecurityContextHolderStrategy
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
MyUser myUser = (MyUser) authentication.getPrincipal();
myUser.setNickname("新的昵称");// 更新SecurityContextRepository
securityContextRepository.saveContext(SecurityContextHolder.getContext(), request, response);
三、总结
通过显式更新SecurityContextHolderStrategy
、SecurityContextRepository
,我们就能完整更新SecurityContext
中的用户信息。如果项目中引入了Spring Session
,Spring Session
维护的登录态也会同步更新。
相关文章:

Spring Security 6.x 系列(6)—— 显式设置和修改登录态信息
一、前言 此篇是对上篇 Spring Security 6.x 系列(5)—— Servlet 认证体系结构介绍 中4.9章节显式调用SecurityContextRepository#saveContext进行详解分析。 二、设置和修改登录态 2.1 登录态存储形式 使用Spring Security框架,认证成功…...
Linux的软件安装
Linux的软件安装 1、rpm软件安装包 RPM(RedHat Package Manager)安装管理 这个机制最早是由Red Hat开发出来,后来实在很好用,因此很多 distributions(发行版)就使用这个机制来作为软件安装的管理方式 。包括Fedora,CentOS,S…...

443. 压缩字符串
这篇文章会收录到 : 算法通关村第十二关-黄金挑战字符串冲刺题-CSDN博客 压缩字符串 描述 : 给你一个字符数组 chars ,请使用下述算法压缩: 从一个空字符串 s 开始。对于 chars 中的每组 连续重复字符 : 如果这一组长度为 1 ,…...
Python面经【6】
Python面经【6】 一、什么是Python的自省机制二、关于Python程序的运行方面,有什么手段可以提升性能三、dict的item()和iteritems()的不同四、说明一个os.path和sys.path分别代表什么五、说一下字典和json的区别六、什么是可变、不可变类型 一、什么是Python的自省机…...

2020年6月9日 Go生态洞察:VS Code Go扩展加入Go项目
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...

C语言错误处理之“非局部跳转<setjmp.h>头文件”
目录 前言 setjmp宏 longjmp函数 使用方法: 实例:测试setjmp与longjmp的使用 前言 通常情况下,函数会返回到它被调用的位置,我们无法使用goto语句改变它的返回的方向,因为goto语句只能跳转到同一函数内的某个标号…...

【SpringCloud】微服务架构设计模式
一、聚合气微服务设计模式 最常见、最简单的设计模式,效果如图所示: 聚合器调用多个服务实现应用程序所需的功能 它可以是一个简单的 Web 页面,将检索到的数据进行处理并展示,也可以是一个更高层次的组合微服务,对…...

【EI会议征稿】第三届航空航天工程与系统国际研讨会(ISAES 2024)
第三届航空航天工程与系统国际研讨会(ISAES 2024) 2024 3rd International Symposium on Aerospace Engineering and Systems 第三届航空航天工程与系统国际研讨会将于2024年3月22-24日在南京召开!会议紧密聚焦“航空航天工程”领域的热点和难点问题,…...
唯创知音WT588F02A-16S录音语音芯片在宠物喂食器中的应用:小芯片,大功能
在现代社会中,宠物已经成为人们生活中的一部分,而宠物喂食器作为宠物养护的重要工具,也越来越受到人们的关注。为了满足人们对宠物喂食器的多样化需求,唯创知音的WT588F02A-16S录音芯片在其中发挥着重要作用。 唯创知音的WT588F0…...

SELinux零知识学习三十七、SELinux策略语言之约束(1)
接前一篇文章:SELinux零知识学习三十六、SELinux策略语言之角色和用户(7) 四、SELinux策略语言之约束 SELinux对策略允许的访问提供了更严格的约束机制,不管策略的allow规则如何。 1. 近距离查看访问决定算法 为了理解约束的用途,先来看一下SELinux Linux安全模块(Lin…...

sqli-labs靶场详解(less25/25a-less28/28a)
在SQL注入过程中难点就是判断注入点 只要注入点确定了 获取数据库数据的过程就是复制 从这关开始 只进行判断注入点了和代码逻辑分析了 因为注入操作太简单了(不演示了) 目录 less-25 less-25a less-26 less-26a less-27 less-27a less-28 less-…...
如何优化 Elasticsearch 查询性能
优化 Elasticsearch 查询性能需要从多个方面入手。通过合理的索引设计、优化查询语句、优化硬件资源和集群架构等方面的优化,可以显著提高 Elasticsearch 的查询性能。 1.索引设计优化 良好的索引设计是优化 Elasticsearch 查询性能的关键。可以通过以下几个方面来…...

成功的蓝图:实现长期成长与卓越表现的 6 项策略
能在收入和利润上持续领先同行的公司寥寥无几,不到四分之一。McKinsey的最新研究揭示了这些增长标杆公司与众不同的六大心态和策略。过度谨慎的公司,尤其在动荡时期,也许能捱过当下,但往往无法发掘全部潜力。考虑到近五年历经前所…...

【JavaEE初阶】认识线程、创建线程
1. 认识线程(Thread) 1.1 概念 1) 线程是什么 一个线程就是一个 "执行流". 每个线程之间都可以按照顺序执行自己的代码. 多个线程之间 "同时" 执行着多份代码. 举例: 还是回到我们之前的银⾏的例⼦中。之前我们主要描…...

uniapp中uni.navigateBack返回后刷新页面数据
文章目录 一、前言1.1、[uni.navigateBack](https://uniapp.dcloud.net.cn/api/router.html#navigateback) 二、方法2.1、父页面设置钩子函数onBackPress2.2、uni.$emit和uni.$on监听通知数据变更2.2.1、子页面2.2.2、父页面 2.3、onShow钩子函数处理数据2.3.1、子页面2.3.2、父…...

sed文本 免交互
目录 什么是sed 概念 格式 基本用法 命令的选项 打印第三行 打印日志文件 打印奇数行 打印偶数行 第三行退出 删除第三行 sed在不打开文件的情况下修改文件内容 在后面添加 选项a 在字符中间添加 \n 实现追加换行 全部追加 在前面插入 选项i 替换 选项c …...

轻巧高效的剃须好工具,DOCO黑刃电动剃须刀上手
剃须刀大家都用过,我比较喜欢电动剃须刀,尤其是多刀头的悬浮剃须刀,感觉用起来很方便,剃须效率也很高。最近我在用一款DOCO小蔻的黑刃电动剃须刀,这款剃须刀轻巧易用,而且性价比超高。 相比于同类产品&…...

第15关 K8s HPA:自动水平伸缩Pod,实现弹性扩展和资源优化
------> 课程视频同步分享在今日头条和B站 大家好,我是博哥爱运维,这节课带来k8s的HPA 自动水平伸缩pod( 视频后面有彩蛋 : ) )。 我们知道,初始Pod的数量是可以设置的,同时业务也分流量高峰和低峰&a…...

接口测试工具(Jmeter)必学技巧
安装 使用JMeter的前提需要安装JDK,需要JDK1.7以上版本 目前在用的是JMeter5.2版本,大家可自行下载解压使用 运行 进入解压路径如E: \apache-jmeter-5.2\bin,双击jmeter.bat启动运行 启动后默认为英文版本,可通过Options – Choos…...
C++面试,说明const和#define的特点和区别
#define只是用来做文本替换的,例如: #define PI 3.1415926 float angel; angel 30 * PI /180; 当程序进行编译的时候。编译器会首先将"#define PI 3.1415926"以后所有代码中的PI都替换成3.1415926,然后进行编译。它的生命周期止…...

【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
离线语音识别方案分析
随着人工智能技术的不断发展,语音识别技术也得到了广泛的应用,从智能家居到车载系统,语音识别正在改变我们与设备的交互方式。尤其是离线语音识别,由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力,广…...

aardio 自动识别验证码输入
技术尝试 上周在发学习日志时有网友提议“在网页上识别验证码”,于是尝试整合图像识别与网页自动化技术,完成了这套模拟登录流程。核心思路是:截图验证码→OCR识别→自动填充表单→提交并验证结果。 代码在这里 import soImage; import we…...
数据库——redis
一、Redis 介绍 1. 概述 Redis(Remote Dictionary Server)是一个开源的、高性能的内存键值数据库系统,具有以下核心特点: 内存存储架构:数据主要存储在内存中,提供微秒级的读写响应 多数据结构支持&…...