SecurityContext和SecurityContextHolder是Spring Security的两个基本类。 SecurityContext
用于存储当前经过身份验证的用户的详细信息,也称为原理。 因此,如果必须获取用户名或任何其他用户详细信息,则需要首先获取此SecurityContext
。 SecurityContextHolder
是一个帮助程序类,它提供对安全上下文的访问。 默认情况下,它使用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)@ResponseBodypublic 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)@ResponseBodypublic 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