Spring Security 从入门到精通之获取认证用户信息(四)

SpringSecurity获取当前登录用户信息 在 Spring Security 中,获取当前登录用户的信息通常涉及到使用 SecurityContextHolder 来获取安全上下文,然后从中提取当前认证信息。以下是一些常用的方法来获取当前登录用户的信息。SecurityContextHolder 是 Spring Security 中的一个核心组件,它用于存储当前安全下文(Securty Context)的详细信息。这些信息包括当前已认证的用户、用户的授予权限以及其他相关的安全细节。 阅读详情

1. 前言

当用户认证通过后,SpringSecurity会将当前用户信息保存起来,以供后续业务流程使用,下面将简单介绍两种获取认证用户的信息。

2 通过SecurityContextHolder获取用户信息

当用户认证通过后,在后续的业务逻辑中还会获取到当前认证的用户信息,在未使用安全框架前,一般是将认证成功的用户存储在HttpSession中,在后续业务逻辑中再从HttpSession中获取用户即可。实际上Spring Security依然是将用户存储在HttpSession中。不过Spring Security在此基础上还对HttpSession中的用户信息作了进一步的封装,Spring Security是将认证的用户信息保存在SecurityContextHolder 对象中。下面我们演示如何从这个类中获取用户信息:

 @GetMapping("/user")
    public ResponseEntity<String> getUser() throws JsonProcessingException {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Map<String,Object> map = new HashMap<>();
        map.put("authentication",authentication);
        String value = objectMapper.writeValueAsString(map);
        return ResponseEntity.ok(value);
    }

当认证成功后,在浏览器中输入http://127.0.0.1:8001/user,并返回如下信息
在这里插入图片描述

2.1. SecurityContextHolder获取用户信息源码分析

首先需要说明的是SecurityContextHolder 中存储的是SecurityContext对象,然后在这个对象中存储了认证用户Authentication对象,下面是三者的关系图:
在这里插入图片描述
首先在SecurityContext在初始化是依靠 SecurityContextHolderStrategy 接口,根据不同的策略生成相应的SecurityContext,在SecurityContextHolder类加载的时候就需要初始化当前策略,我们可以在源码中找到答案:
在这里插入图片描述
SecurityContextHolder 中通过实例化 SecurityContextHolderStrategy 接口不同子类以满足不同的策略需要,
SecurityContextHolderStrategy 接口定义如下:
在这里插入图片描述
SecurityContextHolderStrategy 接口是用来保存SecurityContext对象里,而这个SecurityContext对象里则保存了用户认证Authentication对象,SecurityContext接口定义如下:
在这里插入图片描述
SecurityContextHolderStrategy接口实现类有如下四个:
在这里插入图片描述
SecurityContextHolder类 initializeStrategy方法中默认设置了MODE_THREADLOCAL 策略即 ThreadLocalSecurityContextHolderStrategy 类,这个类源码如下所示:
在这里插入图片描述
可以看到这个类是通过ThreadLocal存储、获取、清空操作的,我们都知道ThreadLocal都是在单个线程中进行读写的,所以在多线程环境下ThreadLocal是线程安全的。这也意味着如果在一个线程中开启了子线程,那么在子线程中是无法获取认证用户信息的。为了解决这个问题SecurityContextHolder 提供了 MODE_INHERITABLETHREADLOCAL策略对应InheritableThreadLocalSecurityContextHolderStrategy 实现,此类定义如下:
在这里插入图片描述
InheritableThreadLocal 是ThreadLocal子类,与 ThreadLocal 不同的是在子线程创建的一瞬间,会自动将父线程中的数据复制到子线程中。所以此策略适用于多线程环境下业务场景。我们可以用以下代码检验一下是否是这样?

    @GetMapping("/user")
    public ResponseEntity<String> getUser() throws JsonProcessingException {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Map<String,Object> map = new HashMap<>();
        map.put("authentication",authentication);
        String value = objectMapper.writeValueAsString(map);
        // 开启子线程获取认证用户信息
        new Thread(()-> {
            Authentication authentication1 = SecurityContextHolder.getContext().getAuthentication();
            if(authentication1 ==null) {
                System.out.println("获取用户信息失败!");
                return;
            }
            System.out.println("子线程获取当前登陆用户名称:"+authentication1.getName());
        }).start();
        return ResponseEntity.ok(value);
    }

项目重启用户认证成功后,浏览器输入:http://127.0.0.1:8001/user 接口控制台输出如下结果:
在这里插入图片描述
可以看到在默认策略下,是无法在子线程中获取用户信息的,如果想要在子线程中获取用户信息,可修改SecurityContextHolder类默认策略,默认的策略是通过System.getProperty进行加载的,在源码中我们不难发现这一点如下所示:
在这里插入图片描述
我们可以在项目启动类上加上VM参数:-Dspring.security.strategy=MODE_INHERITABLETHREADLOCAL
在这里插入图片描述
再次重启重新认证就发现子线程可以获取到当前用户认证的信息了如下所示:
在这里插入图片描述
如果对当前使用场景要求简单的情况下,还可以使用GlobalSecurityContextHolderStrategy,此类使用静态变量来保存SecurityContext对象,不过在web开发中这种策略使用场景不多,此类定义如下所示:
在这里插入图片描述

3. 从HttpServletRequest获取用户信息

  /**
     * 登陆成功后可以直接从HttpServletRequest获取当前已经认证成功的对象
     * @param httpServletRequest HttpServletRequest
     * @return ResponseEntity
     * @throws JsonProcessingException JsonProcessingException
     */
    @GetMapping("/getUserFromServlet")
    public ResponseEntity<String> getUserFromServlet(HttpServletRequest httpServletRequest) throws JsonProcessingException {
        String user = httpServletRequest.getRemoteUser();
        Authentication userPrincipal = (Authentication) httpServletRequest.getUserPrincipal();
        Map<String, Object> map = new HashMap<>();
        map.put("authentication", userPrincipal);
        map.put("user", user);
        String value = objectMapper.writeValueAsString(map);
        return ResponseEntity.ok(value);
    }

3.1 HttpServletRequest获取用户信息源码分析

首先我们看一下HttpServletRequest 类层级关系如下图所示:
在这里插入图片描述
下面我们重点查看一下SecurityContextHolderAwareRequestWrapper#getUserPrincipal 方法
在这里插入图片描述
可以很清晰的看到HttpServletRequest获取的用户认证信息,底层还是通过SecurityContextHolder类进行获取的。

4. SecurityContextHolder 保存认证用户信息流程

Spring Security 将用户登陆成功的用户信息保存在session中,为了能够更好的获取到用户信息,Spring Security 提供了一个SecurityContextHolder类,用来保存用户登陆信息。
具体原理是:当用户登陆成功后,Spring Security会将用户信息保存在SecurityContextHolder中,SecurityContextHolder中的数据保存默认是通过ThreadLocal来实现的,ThreadLocal这个类想必大家都不陌生,我们经常会使用到它来保存一些线程隔离的、全局的变量信息。使用ThreadLocal维护变量时,每个线程都会获得该线程独享一份变量副本。这里通过ThreadLocal 实现了请求线程与用户数据绑定(每一个请求线程都有自己的用户数据),当登陆请求处理完毕后,Spring Security会将SecurityContextHolder中保存用户信息取出并保存在Session中,同时删除SecurityContextHolder保存的用户信息,待下一次请求时,再从session中取出用户信息并保存在SecurityContextHolder中,然后在请求结束时,又会将用户信息从SecurityContextHolder取出并保存在session中并清除SecurityContextHolder中的用户信息。这样做的好处就是可以很方便在Controller或者service中随时获取到用户信息(通过SecurityContextHolder),但是在子线程中获取父线程用户数据就异常麻烦。

5 总结

这里我们学习了如何在Spring Security中获取认证成功的用户信息,下一章我们将继续深入学习Spring Security的整个认证流程,敬请期待

安全认证之SecurityContextHolder 简介 1)SecurityContextHolder是SpringSecurity最基本的组件了,是用来存放SecurityContext的对象,默认是使用ThreadLocal实现的,这样就保证了本线程内所有的方法都可以获得SecurityContext对象。 2) SecurityContextHolder还有其他两种模式,分别为SecurityContextHolder.MODE_GLOBAL和SecurityContextHolder.MODE_INHERITABLETHREADLOCAL... 阅读详情

相关推荐

Spring Security详解(四)认证之鉴权

4 鉴权 从Spring Security的过滤器链中,我们已经发现位于最后的FilterSecurityInterceptor是用来进行权限认证的,这一节将详细分析Spring Security是如何进行权限认证的。 4.1 FilterSecurityInterceptor 源码分析: public class FilterSecurityInterceptor exten...

Jagger的博客 2万+

详解Spring Security中获取当前登录用户的详细信息的几种方法

下面就来详细讲解一下Spring Security获取当前登录用户的详细信息的几种方法。

acerren的博客 7038

Spring Security认证过程

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

weixin_38927257的博客 5193

Spring Security-获取当前登录用户的详细信息

在Spring框架里面,可以通过以下几种方式获取到当前登录用户的详细信息: 1. 在Bean中获取用户信息 Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (!(authentication instanceof AnonymousAuthenticationToken)) { String currentUserName = authentication.ge

xiaokanfuchen86的博客 2524

Spring Security进行登录认证和授权

我们要定制化实现接口来达到从数据库查询用户信息,所以重新写一个实现类。然后认证通过使用用户id生成一个jwt(也就是token),然后用userId作为key,用户信息作为value存入redis中。用户第一次登陆认证流程如下图。导入依赖

afjja的博客 6347

Spring Security认证授权流程

在以上代码的for循环中,第一次拿到的 provider 是一个 Anonymous Authentication Provider。Spring Security会监听这个事件,接收到这个Authentication对象,进而调用 SecurityContextHolder.getContext().setAuthentication(...)方法,将 Authentication Manager返回的 Authentication对象,存储在当前的 Security Context 对象中。

2303_78503642的博客 3922

最新Spring Security实战教程(四)基于内存的用户认证

又是新的一周,博主继续来给大家更新实战教程了,在上一个章节中我们详细介绍了的底层原理,本章节博主将带着大家介绍如何在中实现基于内存的用户认证。虽然基于内存的用户认证,实际开发来说相对来说用的比较少,但某些场景下(如:开发阶段、原型验证、演示环境搭建、单元测试/集成测试、或甚至不需要数据库的简单系统),基于内存的用户认证方式就足以满足需求,为了应对这样需求,博主觉得还是要必要聊一聊基于内存的用户认证。通过本章节的配置示例,相信你已经可以使用的基于内存认证方式来快速搭建安全认证体系。

Micro麦可乐的博客 6325

spring security认证授权流程

在上面的示例代码中,我们实现了UserDetails接口,并指定了用户的角色和密码等详细信息。认证和授权是任何安全体系中的两个主要功能,而在现代Web开发中,Spring Security是最受欢迎和广泛使用的安全框架之一。在本篇文章中,我们将全面介绍Spring Security的认证和授权机制,并提供详细的步骤和示例代码。认证令牌是Spring Security中的核心概念,它包含有关用户身份的信息。用户在认证成功后,Spring Security将使用保存的认证令牌来确定用户是否有权访问特定的资源。

weixin_47618391的博客 5925

从spring-Security获取存储的用户信息

spring-Security获取存储的用户信息 spring-Security获取存储的用户信息 获取spring-Security登录者信息的三种方式 方式1:在后台通过session获取: public String showUsername(HttpServletRequest request){ //通过SecurityContextHolder获得当前线程上绑定的SecurityCo...

weixin_41040866的博客 2158

SpringBoot开发——Spring Security中获取当前登录用户信息的方式

Spring Security中获取当前登录用户信息的方式

bjzhang75的博客 2102

双卡RTX 3090实战:基于vLLM高效部署Qwen2.5-14B BF16大模型的完整指南

本文提供了在双卡RTX 3090上使用vLLM推理框架高效部署Qwen2.5-14B BF16大模型的完整实战指南。内容涵盖硬件配置、系统环境准备、vLLM核心原理与安装、模型获取、详细部署步骤(包括脚本启动与API服务),以及性能调优与避坑技巧,旨在帮助开发者充分利用硬件性能,实现稳定、高速的本地大模型推理服务。

yy01234的博客 1512

Spring Cloud Gateway获取认证用户信息

Spring Cloud Gateway与Spring Security集成。

weixin_46053046的博客 4396

一步一步实现基于COMSOL的单模光纤波导仿真

一步一步实现基于COMSOL的单模光纤波导仿真,简单易懂,跟着博客就能实现

君莫笑lucky的博客 1万+

Spring Security 从入门到精通:在 Spring Boot 项目中的实战指南

Spring Security 的核心功能是认证(Authentication)和授权(Authorization)认证:验证用户身份(“你是谁?”)授权:判断用户是否有权限执行某个操作(“你能做什么?”)它基于 Servlet 过滤器实现,通过一系列过滤器链拦截请求,完成安全校验,且与 Spring Boot 无缝集成,开箱即用。默认的user账号仅用于测试,实际开发中需自定义用户。通过继承配置安全规则。创建配置类。

2501_91015529的博客 1418

01 高等数学 上下册知识点总结

极限与连续 8个等价无穷小 8个常用泰勒公式 高数复习——多元函数微分学 一、概念 一元函数: 可微<=>可导 △y=A△x+o(△x)dy=AdxA=f′(x)\triangle y=A\triangle x+o(\triangle x)\\dy=Adx\\A=f'(x)△y=A△x+o(△x)dy=AdxA=f′(x) 多元函数: 可微=>可导(可导指两个偏导数存在,反之不成立) 可微=>连续(反之不成立) △z=A△x+B△y+o(p)dz=Adx+BdyA=δzδxdx

qq_44292038的博客 1万+

《UDS协议从入门到精通》系列——图解0x85:控制DTC的设置

如何让ECU停止或恢复DTC状态位更新?有哪些注意点?图解+示例教你快速上手UDS 0x85服务!!

车载系统攻城狮 3863

Spring Security实现权限认证与授权

Spring Security实现认证与授权

b2105859的博客 2683

概念解析 | 雷达动态范围

这里存在一个动态范围的问题:强雷达发射信号和弱目标反射信号存在非常大的功率差异,比如传统的脉冲多普勒雷达动态范围可达90dB以上。随着上述技术的发展,预计未来十年雷达接收机动态范围将达到120dB以上,届时雷达的监视能力将得到极大增强。简单来说,雷达动态范围越大,表示接收机噪声越低,对强信号过载保护能力越强,就越能检测到弱信号目标。此外,部分新概念雷达对动态范围提出新的需求,如被动雷达动态范围需大于100dB。当前,随着阵列雷达和数字雷达技术的发展,对雷达接收机动态范围提出了更高要求。

NLOS的博客 1051

【Spring Security】从入门到精通

内附经典案例详解~~

Le vent se lève, il faut tenter de vivre 2407

深入解析Linux驱动开发中的I2C时序及I2C高频面试题

在 I2C 通信中,主设备和从设备的角色有着明确的定义。主设备是发起通信的设备,它负责控制整个通信过程。主设备可以是微控制器、处理器等具有控制能力的设备。

大模型大数据攻城狮的专栏 2764

基于Simulink的永磁同步电机三闭环(位置/速度/电流)控制仿真

本文详细介绍了基于Simulink的永磁同步电机三闭环控制系统设计与实现方法。系统采用位置环、速度环、电流环的三层嵌套结构,通过坐标变换(Clark/Park)实现解耦控制,达到精密定位目的。文章包含完整的建模步骤:从主电路搭建、三环PID设计到坐标变换与SVPWM调制实现,并提供了核心控制算法的MATLAB代码。通过工业机械臂关节场景验证,系统在阶跃响应(稳态误差0.002°)、正弦跟踪(误差0.008°)和抗扰动性能(恢复时间0.05s)方面表现优异。最后还提出了前馈补偿、扰动观测器等优化方向。该方案适

xiaoheshang_123的博客 280

Security登录成功后session域获取用户信息

Security登录成功后session域获取用户信息 标签获取用户名 <%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %> <security:authentication property="principal.username"/> 使用标...

Mr_Li的博客 3861

29.Labview界面设计 --- (下篇)自定义控件库、界面布局与外观设计

1.自定义控件外观(自定义控件)1.1 自定义外观库1.2 手动自定义控件外观2. 前面板控件布局方式(控件排布)2.1 模块化控制布局方式2.2 数据采集布局方式3. 前面板外观优化项(背景设计)3.1 前面板背景设计3.2 前面板窗口整理本节第一部分教大家安装一种可以直接用的自定义控件库,第二部分教大家如何自己设计控件并保存调用。

关注我,更多技术问题欢迎私聊~ 4782

Spring Security+JWT实现认证与授权

目录 一、登录校验流程 3、 整合JWT大致流程 前端响应类 JWT工具类 重写UserDetailsService的方法 重写登录接口 认证过滤器 授权基本流程 封装权限信息 RBAC权限模型 自定义失败处理 认证:验证当前访问系统的是不是本系统的用户,并且要确认具体是哪个用户 授权:经过认证后判断当前用户是否有权限进行某个操作 一、登录校验流程 1、Spring Security 完整流程 SpringSecurity的原理其实就是一个过滤器链,内部包含了提供

weixin_44196561的博客 6959

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

spring security——用户认证流程(二)

一、用户认证逻辑 在自定义用户认证逻辑中我们需要完成的内容有: 处理用户信息获取逻辑 处理用户校验逻辑 处理密码加密解密 1、处理用户信息获取逻辑(UserDetailsService) org.springframework.security.core.userdetails.UserDetailsService UserDetailsService接口用于加载用户...

随笔记 5290

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

【Spring Security OAuth2】- spring security - 认证流程源码级详解

作者简介:大家好,我是哥,前中兴通讯、美团架构师,现某互联网公司联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬学习必须往深处挖,挖的越深,基础越扎实!

smart_an的专栏 1199

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

上一篇: Spring Security 入门之自定义表单登录开发实现(三)
下一篇: Flowable工作流实战快速入门(一)
Galen-gao
博客等级 码龄9年 931粉丝 137原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值