Spring Security中的SecurityContext和SecurityContextHolder是什么?

本文深入探讨了Spring Security中的关键类SecurityContext和SecurityContextHolder的作用。SecurityContext存储已认证用户的信息,而SecurityContextHolder提供了访问SecurityContext的途径,通常使用ThreadLocal进行存储。文章还介绍了如何从SecurityContextHolder中获取当前登录用户的详细信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SecurityContextSecurityContextHolder是Spring Security的两个基本类。 SecurityContext用于存储当前经过身份验证的用户的详细信息,也称为原理。 因此,如果必须获取用户名或任何其他用户详细信息,则需要首先获取此SecurityContextSecurityContextHolder是一个帮助程序类,它提供对安全上下文的访问。 默认情况下,它使用ThreadLocal对象存储安全性上下文,这意味着即使不传递SecurityContext对象,该安全性上下文也始终可用于同一执行线程中的方法。 不过,不必担心Web应用程序中的ThreadLocal内存泄漏 ,Spring Security会负责清理ThreadLocal。

顺便说一句,这不是SecurityContextHolder可以存储当前SecurityContext的唯一方法,可以在启动时为其配置策略,以指定如何存储上下文。 例如,可以将SecurityContextHolder.MODE_GLOBAL策略用于独立的应用程序。

要学习的关键是, 如何从SecurityContextHolder获得SecurityContext? 然后从中检索当前的用户详细信息? 例如,如果您想知道当前登录用户的用户名,那么如何在Spring security中获得该用户名?

为了获取当前的用户名,首先需要一个SecurityContext ,它是从SecurityContextHolder获得的。 此SecurityContext将用户详细信息保留在Authentication对象中,该对象可以通过调用getAuthentication()方法获得。

一旦获得身份验证对象,就可以转换为UserDetails或按原样使用它。 UserDetails对象是Spring Security用于保留用户相关信息的对象。

如何在Spring Security中获取当前的登录用户名

这是获取Spring安全性中的安全性上下文并获取当前登录用户的名称的代码:

Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

if (principal instanceof UserDetails) {
  String username = ((UserDetails)principal).getUsername();
} else {
  String username = principal.toString();
}

getContext()返回的对象是SecurityContext接口的实例。 这是存储在线程本地存储中的对象。

getPrincipal()方法通常在Spring Security中返回UserDetails对象,该对象包含当前登录用户的所有详细信息。

无论如何,如果您仔细观察,您会发现在考虑Spring依赖注入时,这并不是一个很好的代码。 因此,如果您需要了解当前登录的用户详细信息(例如在Spring MVC控制器中),建议您声明一个依赖项,然后让Spring为您提供Principal对象,而不是查询它们并创建一个紧密耦合的系统。

这是一个例子

import java.security.Principal;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MVCController {

  @RequestMapping(value = "/username", method = RequestMethod.GET)
  @ResponseBody
  public String currentUserName(Principal principal) {
     return principal.getName();
  }

}

另外,您也可以要求提供Authentication对象而不是Principal对象,如下所示:

import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class SpringMVCController {

  @RequestMapping(value = "/username", method = RequestMethod.GET)
  @ResponseBody
  public String currentUserName(Authentication authentication) {
     return authentication.getName();
  }
}

如果您想了解更多方法,还可以参阅我的文章有关在Spring Security中获取当前用户名的3种方法 ,在此我讨论了几种在Spring MVC控制器中获取当前用户名的更多方法。

这就是Spring安全性中的安全性上下文,以及如何从SecurityContextHolder类获取SecurityContext的全部内容。 这些是一些基本类,因此您必须熟悉它们。

存储部分(即SecurityContext存储在ThreadLocal是可选的,但最好了解详细信息。 请记住,如果您需要用户详细信息(例如用户名等),则最好在Spring MVC控制器中请求Principal或Authentication对象,而不要使用SecurityContextHolder来获取它们。

感谢您到目前为止阅读本文。 如果您喜欢此Spring Security教程,请与您的朋友和同事分享。 如果您有任何疑问或反馈,请留言。

翻译自: https://www.javacodegeeks.com/2018/02/securitycontext-securitycontextholder-spring-security.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值