获取登录用户的认证信息
字数: 0 字 时长: 0 分钟
1.前言
大家好,我是Leo哥🫣🫣🫣,接到上一节,我们学习通过SpringSecurity退出登录之后的JSON处理。这篇文章我们主要来介绍一下登录成功之后如何获取用户信息。好了,话不多说让我们开始吧😎😎😎。
2.概述
在这篇文章中我们添加了一个主页面,用超链接来进行退出登录,而不是频繁在地址栏输入URL。
3.获取用户认证信息
我们登录之后,我们用户的信息,存储在哪里呢,我们又该如何进行获取呢,今天我们接着往下聊。
用户登录成功后,用户的信息存储在 SecurityContext
中。SecurityContext
是由 SecurityContextHolder
管理的,它是 Spring Security 的核心组件之一。
存储用户信息的过程
- 用户认证:当用户通过表单登录或其他认证方式成功登录后,SpringSecurity 会创建一个 **Authentication ** 对象,该对象包含用户的认证信息。
- 存储认证信息:
Authentication
对象被存储在SecurityContext
中。 - 上下文管理:
SecurityContext
由SecurityContextHolder
管理,通常与当前线程绑定,以确保在请求处理过程中可以随时访问用户信息。
我们通过官网的一张图更清晰的来了解SecurityContextHolder。
此时我们就可以通过 SecurityContextHolder
来获取用户的认证信息了。话不多说,我们直接上代码。
我们这里在我们之前的hello接口添加必要代码即可。
此时,登录成功之后访问hello接口,即可在idea控制台中看到我们的信息。
4. 探知原理
上面我们知道了通过 SecurityContextHolder 这个类来获取用户认证信息,那么内部究竟是如何处理的呢。我们打开源码一探究竟。
SecurityContextHolder
通过 initializeStrategy
方法初始化安全上下文的存储策略,根据配置选择适当的策略类来管理安全上下文。在默认情
况下,使用 ThreadLocal
存储安全上下文,可以根据需要切换到可继承的线程本地变量策略。
那么,用户的认证数据是在什么时候存储的呢?
表单认证时,在 AbstractAuthenticationProcessingFilter 过滤器的 doFilter() 方法中,调用UsernamePasswordAuthenticationFilter 过滤器的 attemptAuthentication() 方法进行用户认证,认证通过则返回认证后的 Authentication 对象,否则返回 null 。认证成功后,会再调用自已的successfulAuthentication() 方法存储当前的认证信息。
在 AbstractAuthenticationProcessingFilter 过滤器的 successfulAuthentication() 方法中,把验证通过的用户认证信息先存入 SecurityContext ,然后再调用ThreadLocalSecurityContextHolderStrategy 类中的 setContext() 方法,把 SecurityContext 存入ThreadLocal 中。
调用 ThreadLocalSecurityContextHolderStrategy 类中的 setContext() 方法,把 SecurityContext 存入 ThreadLocal 中。
5. 网页拓展
除了在我们Java后端通过 SecurityContextHolder 获取用户的登录信息之外,我们还可以通过在前端网页上获取我们的登录信息,下面跟着一起来操作吧。
5.1 引入依赖
在pom文件中引入以下依赖。
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
</dependency>
5.2 引入命名空间
在login.html中引入指定的命名空间。
<html lang="en" xmlns:th="https://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
5.3 在网页中使用
<!--获取登录用户信息-->
<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>
6. 小结
- SecurityContextHolder:提供对 SecurityContext 安全上下文的访问,默认情况下,它使用 ThreadLocal 对象来存储安全上下文,它是线程安全的
- SecurityContext:安全上下文,内部包含了当前认证用户的详细信息。
- Authentication:存储当前用户的详细信息(Principal 用户信息、Credentials 密码信息、Authorities 权限信息)。
SecurityContextHolder有三种工作策略模式:
- MODE_THREADLOCAL(默认):本地线程模式,将认证用户信息和当前线程绑定存在ThreadLocal 中,在同一个线程内可以获取到相同的安全上下文
- MODE_INHERITABLETHREADLOCAL:可继承的本地线程模式,将安全上下文复制给当前线程的子线程,就可以实现多个父子线程可以共享安全上下文
- MODE_GLOBAL:全局模式,所有线程都能看到相同的安全上下文实例
7. 总结
以上便是本文的全部内容,本人才疏学浅,文章有什么错误的地方,欢迎大佬们批评指正!我是Leo,一个在互联网行业的小白,立志成为更好的自己。
如果你想了解更多关于Leo,可以关注公众号-程序员Leo,后面文章会首先同步至公众号。