尝试 Autowiring SecurityContextHolder 我收到错误
required a bean of type 'org.springframework.security.core.context.SecurityContextHolder' that could not be found.
事实证明它可以从代码的任何部分使用,例如
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
为什么它不是一个 bean,它是如何在幕后初始化的? 是否有其他类似的静态实用程序类可以从任何地方使用以及如何找到它们?
最佳答案
SecurityContextHolder
是一个实用程序类,它声明了一堆 static
方法,可以使用类名访问。
实例化实用程序类没有多大意义(为了强调这一点,它们的构造函数通常是私有(private)的),因此 SecurityContextHolder
不是上下文中的 Bean,因此无法(也不需要)注入(inject)它。
目的SecurityContextHolder
方便访问 SecurityContext
,其中包含特定于当前经过身份验证的用户的信息。另外,SecurityContextHolder
提供各种管理策略SecurityContext
:
-
MODE_THREADLOCAL
是默认的,适用于所谓的基于 servlet 的 Web 应用程序,该应用程序使用每个请求线程模型。在这种情况下,每个线程都有自己的上下文,Spring 使用TreadLocal
管理上下文。 -
MODE_INHERITABLETHREADLOCAL
与前一个类似,但有一个区别 - 它允许每个请求使用多个线程,如果我们生成一个新线程,它会继承父线程的上下文。 -
MODE_GLOBAL
- 不适合服务器使用。该策略并非基于TreadLocal
,每个线程都应该看到相同的上下文。并且可以在独立应用程序中使用(例如在 Swing 客户端中)。
这是 Spring Security documentation 的简短引用(如果您想了解更多信息,请仔细查看此链接):
10.1. SecurityContextHolder
At the heart of Spring Security’s authentication model is the
SecurityContextHolder
. It contains theSecurityContext
. securitycontextholderThe
SecurityContextHolder
is where Spring Security stores the details of who is authenticated. Spring Security does not care how theSecurityContextHolder
is populated. If it contains a value, then it is used as the currently authenticated user....
因此,回顾一下 SecurityContextHolder
的主要目的就是管理SecurityContext
。安全上下文旨在提供对用户的 Authentication
的访问.
Authentication
代表当前经过身份验证的用户。自从 Authentication
一个 Bean,它可以通过另一个 Bean 中的依赖注入(inject)来提供,例如作为方法参数。
让我们看一个例子。假设我们有一个 Controller ,其端点返回 Foo
的实例这需要 Authentication
中的一些用户信息:
@RestController
public class FooController {
@GetMapping("/foo")
Foo getFoo(Authentication a) {
return FooUtils.generateFoo(a);
}
}
它利用generateFoo()
方法通过传递 Authentication
注入(inject)了一个参数。方法generateFoo()
位于FooUtils
这是一个实用程序类。
public class FooUtils {
public static Foo generateFoo(Authentication a) {
return new Foo(a.getPrincipal());
}
}
Authentication
无法注入(inject) FooUtils
的方法中,因为它不是 Bean,因此它是由调用者分发的。如果我们想象调用链会更长,即调用端点方法和FooUtils.generateFoo()
之间会有更多操作。路过的话不太方便Authentication
通过几种不会使用它的方法。
相反,可以使用 SecurityContextHolder
并获得Authentication
就在 FooUtils
内:
public class FooUtils {
public static Foo generateFoo() {
Authentication a = SecurityContextHolder
.getContext()
.getAuthentication();
return new Foo(a.getPrincipal());
}
}
关于java - SecurityContextHolder 不是一个 Bean 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74458719/