我的编程空间,编程开发者的网络收藏夹
学习永远不晚

SpringSecurity获取用户认证信息的实现流程

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

SpringSecurity获取用户认证信息的实现流程

登录用户数据获取

SecurityContextHolder

​ Spring Security 会将登录用户数据保存在 Session 中。但是,为了使用方便,Spring Security在此基础上还做了一些改进,其中最主要的一个变化就是线程绑定。当用户登录成功后,Spring Security 会将登录成功的用户信息保存到 SecurityContextHolder 中。

​ SecurityContextHolder 中的数据保存默认是通过ThreadLocal 来实现的,使用 ThreadLocal 创建的变量只能被当前线程访问,不能被其他线程访问和修改,也就是用户数据和请求线程绑定在一起。当登录请求处理完毕后,Spring Security 会将 SecurityContextHolder 中的数据拿出来保存到 Session 中,同时将 SecurityContexHolder 中的数据清空。以后每当有请求到来时,Spring Security 就会先从 Session 中取出用户登录数据,保存到SecurityContextHolder 中,方便在该请求的后续处理过程中使用,同时在请求结束时将 SecurityContextHolder 中的数据拿出来保存到 Session 中,然后将SecurityContextHolder 中的数据清空。

​ 实际上 SecurityContextHolder 中存储是 SecurityContext,在 SecurityContext 中存储是 Authentication。

这种设计是典型的策略设计模式:

public class SecurityContextHolder {
	public static final String MODE_THREADLOCAL = "MODE_THREADLOCAL";
	public static final String MODE_INHERITABLETHREADLOCAL = "MODE_INHERITABLETHREADLOCAL";
	public static final String MODE_GLOBAL = "MODE_GLOBAL";
	private static final String MODE_PRE_INITIALIZED = "MODE_PRE_INITIALIZED";
	private static SecurityContextHolderStrategy strategy;
  //....
	private static void initializeStrategy() {
		if (MODE_PRE_INITIALIZED.equals(strategyName)) {
			Assert.state(strategy != null, "When using " + MODE_PRE_INITIALIZED
					+ ", setContextHolderStrategy must be called with the fully constructed strategy");
			return;
		}
		if (!StringUtils.hasText(strategyName)) {
			// Set default
			strategyName = MODE_THREADLOCAL;
		}
		if (strategyName.equals(MODE_THREADLOCAL)) {
			strategy = new ThreadLocalSecurityContextHolderStrategy();
			return;
		}
		if (strategyName.equals(MODE_INHERITABLETHREADLOCAL)) {
			strategy = new InheritableThreadLocalSecurityContextHolderStrategy();
			return;
		}
		if (strategyName.equals(MODE_GLOBAL)) {
			strategy = new GlobalSecurityContextHolderStrategy();
			return;
		}
    //.....
  }
}
  • MODE THREADLOCAL:这种存放策略是将 SecurityContext 存放在 ThreadLocal中,大家知道 Threadlocal 的特点是在哪个线程中存储就要在哪个线程中读取,这其实非常适合 web 应用,因为在默认情况下,一个请求无论经过多少 Filter 到达 Servlet,都是由一个线程来处理的。这也是 SecurityContextHolder 的默认存储策略,这种存储策略意味着如果在具体的业务处理代码中,开启了子线程,在子线程中去获取登录用户数据,就会获取不到。
  • MODE INHERITABLETHREADLOCAL:这种存储模式适用于多线程环境,如果希望在子线程中也能够获取到登录用户数据,那么可以使用这种存储模式。
  • MODE GLOBAL:这种存储模式实际上是将数据保存在一个静态变量中,在 JavaWeb开发中,这种模式很少使用到。

SecurityContextHolderStrategy

通过 SecurityContextHolder 可以得知,SecurityContextHolderStrategy 接口用来定义存储策略方法

public interface SecurityContextHolderStrategy {
	void clearContext();
	SecurityContext getContext();
	void setContext(SecurityContext context);
	SecurityContext createEmptyContext();
}

接口中一共定义了四个方法:

  • clearContext:该方法用来清除存储的 SecurityContext对象。
  • getContext:该方法用来获取存储的 SecurityContext 对象。
  • setContext:该方法用来设置存储的 SecurityContext 对象。
  • create Empty Context:该方法则用来创建一个空的 SecurityContext 对象。

代码中获取认证之后用户数据

@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String hello() {
      Authentication authentication = SecurityContextHolder
        .getContext().getAuthentication();
      User principal = (User) authentication.getPrincipal();
      System.out.println("身份 :"+principal.getUsername());
      System.out.println("凭证 :"+authentication.getCredentials());
      System.out.println("权限 :"+authentication.getAuthorities());
      return "hello security";
    }
}

多线程情况下获取用户数据

@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String hello() {
      new Thread(()->{
        Authentication authentication = SecurityContextHolder
          .getContext().getAuthentication();
        User principal = (User) authentication.getPrincipal();
        System.out.println("身份 :"+principal.getUsername());
        System.out.println("凭证 :"+authentication.getCredentials());
        System.out.println("权限 :"+authentication.getAuthorities());
      }).start();
      return "hello security";
    }
}

可以看到默认策略,是无法在子线程中获取用户信息,如果需要在子线程中获取必须使用第二种策略,默认策略是通过 System.getProperty 加载的,因此我们可以通过增加 VM Options 参数进行修改。

-Dspring.security.strategy=MODE_INHERITABLETHREADLOCAL

页面上获取用户信息

引入依赖

<dependency>
  <groupId>org.thymeleaf.extras</groupId>
  <artifactId>thymeleaf-extras-springsecurity5</artifactId>
  <version>3.0.4.RELEASE</version>
</dependency>

页面加入命名空间

<html lang="en" xmlns:th="https://www.thymeleaf.org" 
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">

页面中使用

<!--获取认证用户名-->
<ul>
  <li sec:authentication="principal.username"></li>
  <li sec:authentication="principal.authorities"></li>
  <li sec:authentication="principal.accountNonExpired"></li>
  <li sec:authentication="principal.accountNonLocked"></li>
  <li sec:authentication="principal.credentialsNonExpired"></li>
</ul>

到此这篇关于Spring Security获取用户认证信息的实现流程的文章就介绍到这了,更多相关Spring Security获取认证信息内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

SpringSecurity获取用户认证信息的实现流程

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

SpringSecurity获取用户认证信息的实现流程

SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了SpringIoC,DI和AOP功能,为应用系统提供声明式的安全访问控制功能
2022-12-27

微信小程序实现授权登录之怎么获取用户信息

这篇文章主要讲解了“微信小程序实现授权登录之怎么获取用户信息”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“微信小程序实现授权登录之怎么获取用户信息”吧!小程序登录小程序可以通过微信官方提供的
2023-06-30

Android应用中怎么实现用户登录认证流程

用户登录认证流程是Android应用中非常重要的一部分,它可以保护用户的隐私信息并确保数据的安全性。以下是一个基本的用户登录认证流程的实现步骤:在应用中创建一个登录界面,包括用户名和密码的输入框以及登录按钮。用户输入用户名和密码后,点击登
Android应用中怎么实现用户登录认证流程
2024-04-03

微信小程序如何实现获取用户信息替换用户名和头像到首页

本篇内容介绍了“微信小程序如何实现获取用户信息替换用户名和头像到首页”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、形成空白文件1、点击
2023-06-30

微信公众号开发中使用Java如何实现获取用户的信息

微信公众号开发中使用Java如何实现获取用户的信息?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1、首先需要到微信网站去设置一下,我是直接用的微信测试号。        接
2023-05-31

微信公众平台开发中使用Java如何实现获取用户的信息

本篇文章为大家展示了微信公众平台开发中使用Java如何实现获取用户的信息,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。(一)用户微信消息的获取实现在关注者与公众号产生消息交互后,公众号可获得关注者的
2023-05-31

Python利用多线程枚举实现获取wifi信息

这篇文章主要为大家详细介绍了Python如何利用枚举字典的方式来实现获取wifi信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
2022-12-14

Android实现获取应用程序相关信息列表的方法

本文所述为Androdi获取手机应用列表的方法,比如获取到Android应用的软件属性、大小和应用程序路径、应用名称等,获取所有已安装的Android应用列表,包括那些卸载了的,但没有清除数据的应用程序,同时在获取到应用信息的时候,判断是不
2022-06-06

利用Qt实现获取计算机的硬件信息

在开发时,常常会需要用到计算机的相关信息。利用这些信息,我们可以开发一些辅助模块。本文将利用Qt实现获取计算机的硬件信息,感兴趣的可以尝试一下
2022-12-09

小程序开发中如何调用接口获取登录凭证进而换取用户登录态信息

这篇文章主要为大家展示了小程序开发中如何调用接口获取登录凭证进而换取用户登录态信息,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带大家一起来研究并学习一下“小程序开发中如何调用接口获取登录凭证进而换取用户登录态信息”这篇文章
2023-06-26

微信小程序授权获取用户信息之wx.getUserInfo 切换到 wx.getUserProfile的使用(已弃用)

目录 更新:wx.getUserProfile() 已弃用背景一、小程序获取用户信息相关接口调整说明二、wx.getUserProfile的使用1. 之前的wx.getUserInfo接口的使用2. 现在的wx.getUserPro
2023-08-19

微信小程序分享及授权获取用户信息接口调整的方法

这篇文章主要介绍了微信小程序分享及授权获取用户信息接口调整的方法的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇微信小程序分享及授权获取用户信息接口调整的方法文章都会有所收获,下面我们一起来看看吧。调整方案具体如
2023-06-26

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录