Spring Security 6.x 系列(6)—— 显式设置和修改登录态信息

news2024/11/17 7:47:11

一、前言

此篇是对上篇 Spring Security 6.x 系列(5)—— Servlet 认证体系结构介绍 中4.9章节显式调用SecurityContextRepository#saveContext进行详解分析。

二、设置和修改登录态

2.1 登录态存储形式

使用Spring Security框架,认证成功后的用户信息会放在Authentication对象的Principal中,
Authentication对象又会被放入SecurityContext中,而SecurityContext 存在这2个地方:

  • SecurityContextHolderStrategy :线程级别的SecurityContext持有策略。有全局共享、线程继承、线程隔离等几种获取上下文的方式(上文有过介绍)。

  • SecurityContextRepository:持久化SecurityContext ,默认存入HttpServletRequestHttpSession

在代码中,我们要获取用户登录信息,可以通过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 */
    @Deprecated
    SecurityContext 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,这是委派代理存储,代理的对象是 RequestAttributeSecurityContextRepositoryHttpSessionSecurityContextRepository,所以在默认的情况下,用户登录成功之后,在这里就把登录用户数据分别存入到HttpSessionSecurityContextRepositoryRequestAttributeSecurityContextRepository中。

在这里插入图片描述

部分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())
        );
}

这里DelegatingSecurityContextRepositorySpring 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);

三、总结

通过显式更新SecurityContextHolderStrategySecurityContextRepository ,我们就能完整更新SecurityContext 中的用户信息。如果项目中引入了Spring SessionSpring Session维护的登录态也会同步更新。

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

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

相关文章

Django回顾【一】

一、Web应用程序 Web应用程序是一种可以通过Web访问的应用程序&#xff0c;程序的最大好处是用户很容易访问应用程序&#xff0c;用户只需要有浏览器即可&#xff0c;不需要再安装其他软件。应用程序有两种模式C/S、B/S。 C/S&#xff1a;客户端<----->服务端 例如My…

第二十章,多线程

创建线程 有两种方式&#xff0c;分别为继承Java.lang.Thread类与实现Java.lang.Runnable接口 继承Thread类 Thread常用的两个构造方法语法 public Thread&#xff08;&#xff09;&#xff1b; public Thread&#xff08;String threadName&#xff09;&#xff1b; 继承…

揭秘Java三宝:final,static,volatile,面试中不可不知的关键字秘籍!

大家好&#xff0c;我是小米&#xff0c;一名热爱技术分享的程序员。最近在和小伙伴们聊天时&#xff0c;发现有不少小伙伴对于Java中的一些关键字&#xff0c;比如final&#xff0c;static&#xff0c;volatile等&#xff0c;还是感到有些懵懂。为了帮助大家更好地理解这些概念…

企业如何选择安全又快速的大文件传输平台

在现代信息化社会&#xff0c;数据已经成为各个行业的重要资源&#xff0c;而数据的传输和交换则是数据价值的体现。在很多场合&#xff0c;企业需要传输或接收大文件&#xff0c;例如设计图纸、视频素材、软件开发包、数据库备份等。这些文件的大小通常在几百兆字节到几十个字…

HashMap的实现原理

1.HashMap实现原理 HashMap的数据结构&#xff1a; *底层使用hash表数据结构&#xff0c;即数组链表红黑树 当我们往HashMap中put元素时&#xff0c;利用key的hashCode重新hash计算出当前对象的元素在数组中的下标 存储时&#xff0c;如果出现hash值相同的key&#xff0c;此时…

HarmonyOS-Service服务开发(一)

文章目录 创建新项目启动Serviceets获取service的bundleName DataAbility开发指导开发Data步骤创建Data 创建新项目 ServiceAbility开发指导 在config.json中也有配置出现 启动Service ets获取service的bundleName 项目的bundleName service的bundleName 这里serviceAbil…

模板上新|2023年10月DataEase模板市场上新动态

DataEase开源数据可视化分析平台于2022年6月正式发布模板市场&#xff08;https://dataease.io/templates/&#xff09;。模板市场旨在为DataEase用户提供专业、美观、拿来即用的仪表板模板&#xff0c;方便用户根据自身的业务需求和使用场景选择对应的仪表板模板&#xff0c;并…

easyExcel自定义导出,指定列,设置请求头背景色,加入合计行,设置合计行字体,背景色等等

效果图 1.引入easyExcel pom <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.1</version></dependency> 2.工具类-自定义样式handler-CustomCellWriteHandler import java.util…

skywalking告警UI界面有告警信息,webhook接口没有回调,400错误

400错误就是回调接口返回数据的属性对应不上 PostMapping(“/webhook”) public void webhook(RequestBody List alarmMessageList) 自定义的实体类AlarmMessage有问题 只能去官网找了 告警实体类官网 Getter EqualsAndHashCode RequiredArgsConstructor NoArgsConstructor(fo…

数据库基础入门 — 关联查询

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 本…

GAN:DCGAN-深度卷积生成对抗网络

论文&#xff1a;https://arxiv.org/pdf/1511.06434.pdf 发表&#xff1a;ICLR 2016 一、架构创新 1&#xff1a;全卷积网络&#xff1a;用逐步卷积代替确定性的空间池化函数&#xff08;如maxpooling&#xff09;&#xff0c;使网络学习自己的空间下采样。使用这种方法&#…

京东大数据(京东运营数据采集):2023年10月京东牛奶乳品行业品牌销售排行榜

鲸参谋监测的京东平台10月份牛奶乳品市场销售数据已出炉&#xff01; 10月份&#xff0c;牛奶乳品整体销售上涨。鲸参谋数据显示&#xff0c;今年10月&#xff0c;京东平台上牛奶乳品的销量将近1700万&#xff0c;同比增长1%&#xff1b;销售额将近17亿&#xff0c;同比增长约5…

双通道 12V 直流电机驱动芯片GC8548,可替代LV8548/LV8549/ONSEMI,内置 LDO,不需要逻辑电源,输入 兼容 3.3V 与 5V

GC8548 是一款双通道 12V 直流电机驱动芯 片&#xff0c;为摄像机、消费类产品、玩具和其他低压或 者电池供电的运动控制类应用提供了集成的电机 驱动解决方案。芯片一般用来驱动两个直流电机 或者驱动一个步进电机。 它可以工作在 3.8~12V 的电源电压上&#xff0c; 每通道能提…

如何通过内网穿透实现公网远程ssh连接kali系统

文章目录 1. 启动kali ssh 服务2. kali 安装cpolar 内网穿透3. 配置kali ssh公网地址4. 远程连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 简单几步通过[cpolar 内网穿透](cpolar官网-安全的内网穿透工具 | 无需公网ip | 远程访问 | 搭建网站)软件实现ssh远程连接kali 1…

中小型公司如何搭建运维平台,rancher、kubersphere、rainbond

很多开发人员应该是了解过运维发布相关的平台或实际操作过应用发布&#xff0c;但又通常不是十分熟悉。在一个初创公司&#xff0c;或者没有成熟的运维发布平台的公司&#xff0c;如果让你来搭建一套发布平台&#xff0c;你应该如何去抉择呢&#xff1f; 这里我简单介绍几种。…

“大型”基础模型中幻觉的调查

Abstract 基础模型 (FM) 中的幻觉是指生成偏离事实或包含捏造信息的内容。这篇调查论文广泛概述了近期旨在识别、阐明和解决幻觉问题的努力&#xff0c;特别关注“大型”基础模型&#xff08;LFM&#xff09;。该论文对LFM特有的各种类型的幻觉现象进行了分类&#xff0c;并建…

Mybatis 源码搭建

文章目录 源码下载测试模块搭建学习博客 源码下载 首先下载mybatis-parent的源码&#xff1a;gitee地址 > https://gitee.com/callback_lab/mybatis-parent.git 然后下载mybatis的源码&#xff1a;gitee地址 > https://gitee.com/callback_lab/mybatis-src.git 带中文…

pandas(八)--实战一下

背景 收到一批数据&#xff0c;数据形式。采集数据的间隔时间是10分钟&#xff0c;全天采集数据&#xff0c;每天的数据量是144条 处理后的数据形式 分析 去除表格中的q的异常值&#xff0c;置为0去除重复行将原始表格中的date分裂成日期和时间缺失的时间点数据补0&#x…

最新的外贸自建站教程?做外贸如何建网站?

外贸自建站教程步骤有哪些&#xff1f;海洋建站如何做网站搭建&#xff1f; 想要了解关于外贸自建站的最新教程吗&#xff1f;外贸自建站不再是高不可攀的难题&#xff0c;相反&#xff0c;它为企业提供了更多的机会和自主掌握业务的空间。海洋建站将为您提供一份全面的指南&a…

山寨Stream API设计分析

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 私以为&#xff0c;Jav…