SpringSecurity6 | 获取登录用户的认证信息

542 阅读4分钟

SpringSecurity6 | 获取登录用户的认证信息

image-20231030235443828

1.前言

大家好,我是Leo哥🫣🫣🫣,接到上一节,我们学习通过SpringSecurity退出登录之后的JSON处理。这篇文章我们主要来介绍一下登录成功之后如何获取用户信息。好了,话不多说让我们开始吧😎😎😎。

2.概述

这篇文章中我们添加了一个主页面,用超链接来进行退出登录,而不是频繁在地址栏输入URL。

image-20231227095749441

3.获取用户认证信息

我们登录之后,我们用户的信息,存储在哪里呢,我们又该如何进行获取呢,今天我们接着往下聊。

用户登录成功后,用户的信息存储在 SecurityContext 中。SecurityContext 是由 SecurityContextHolder 管理的,它是 Spring Security 的核心组件之一。

存储用户信息的过程

  1. 用户认证:当用户通过表单登录或其他认证方式成功登录后,SpringSecurity 会创建一个 Authentication 对象,该对象包含用户的认证信息。
  2. 存储认证信息Authentication 对象被存储在 SecurityContext 中。
  3. 上下文管理SecurityContextSecurityContextHolder 管理,通常与当前线程绑定,以确保在请求处理过程中可以随时访问用户信息。

我们通过官网的一张图更清晰的来了解SecurityContextHolder。

image-20240621140850737

此时我们就可以通过 SecurityContextHolder 来获取用户的认证信息了。话不多说,我们直接上代码。

我们这里在我们之前的hello接口添加必要代码即可。

image-20240621140440102

此时,登录成功之后访问hello接口,即可在idea控制台中看到我们的信息。

image-20240621140711781

4. 探知原理

上面我们知道了通过 SecurityContextHolder 这个类来获取用户认证信息,那么内部究竟是如何处理的呢。我们打开源码一探究竟。

image-20240621141524116

SecurityContextHolder 通过 initializeStrategy 方法初始化安全上下文的存储策略,根据配置选择适当的策略类来管理安全上下文。在默认情

况下,使用 ThreadLocal 存储安全上下文,可以根据需要切换到可继承的线程本地变量策略。

那么,用户的认证数据是在什么时候存储的呢?

表单认证时,在 AbstractAuthenticationProcessingFilter 过滤器的 doFilter() 方法中,调用UsernamePasswordAuthenticationFilter 过滤器的 attemptAuthentication() 方法进行用户认证,认证通过则返回认证后的 Authentication 对象,否则返回 null 。认证成功后,会再调用自已的successfulAuthentication() 方法存储当前的认证信息。

image-20240621141759834

在 AbstractAuthenticationProcessingFilter 过滤器的 successfulAuthentication() 方法中,把验证通过的用户认证信息先存入 SecurityContext ,然后再调用ThreadLocalSecurityContextHolderStrategy 类中的 setContext() 方法,把 SecurityContext 存入ThreadLocal 中。

image-20240621141842244

调用 ThreadLocalSecurityContextHolderStrategy 类中的 setContext() 方法,把 SecurityContext 存入 ThreadLocal 中。

image-20240621141912757

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,后面文章会首先同步至公众号。