在spring security中,SecurityContext包含一个Authentication对象,我们通常使用SecurityContextHolder来获取当前的Authentication,如下所示
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
那么为什么不直接通过SecurityContextHolder中的SecurityContextHolderStrategy来获取或设置Authentication,Spring Security架构中SecurityContext的用途是什么?
例如,ThreadLocalSecurityContextHolderStrategy 可能是
final class ThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy {
private static final ThreadLocal<Authentication> contextHolder = new ThreadLocal<>();
@Override
public Authentication getAuthentication() {
return contextHolder.get();
}
@Override
public void setAuthentication(Authentication authentication) {
contextHolder.set(authentication);
}
...
}
// when obtain Authentication
SecurityContextHolder.getAuthentication();
SecurityContextHolder
继承了SecurityContext
和SecurityContextHolderStrategy
,这意味着您作为用户可以选择您想要使用的策略。
在您提供的代码示例中,您实现了一种策略,即 ThreadLocal 策略。虽然 Springs securitycontext 有多种策略,您可以根据您正在编写的应用程序类型进行选择。
摘自文档:
默认情况下,SecurityContextHolder 使用 ThreadLocal 来存储这些详细信息,这意味着 SecurityContext 始终可用于同一线程中的方法,即使 SecurityContext 没有作为参数显式传递给这些方法。
除了其他策略,还是文档:
某些应用程序并不完全适合使用 ThreadLocal,因为它们使用线程的特定方式。例如,Swing 客户端可能希望 Java 虚拟机中的所有线程使用相同的安全上下文。
您可以在启动时使用策略配置 SecurityContextHolder,以指定您希望如何存储上下文。
对于独立应用程序,您可以使用 SecurityContextHolder.MODE_GLOBAL 策略。其他应用程序可能 想让安全线程生成的线程也假设相同 安全身份。您可以通过使用来实现这一点 SecurityContextHolder.MODE_INHERITABLETHREADLOCAL。您可以更改 模式由默认的 SecurityContextHolder.MODE_THREADLOCAL 中的两种 方法。第一个是设置系统属性。第二个是调用 SecurityContextHolder 上的静态方法。大多数应用程序不需要 从默认值更改。但是,如果您这样做,请查看 SecurityContextHolder 的 JavaDoc 了解更多信息。
因此,根据您的需求,您可以选择您想要的策略。
就是这个原因。