多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
最基本的对象是`SecurityContextHolder`。 这是我们存储应用程序当前安全上下文的详细信息的地方,其中包括当前使用该应用程序的主体的详细信息。 默认情况下,`SecurityContextHolder`使用`ThreadLocal`来存储这些详细信息,这意味着安全上下文始终可用于同一执行线程中的方法,即使安全上下文未作为这些方法的参数显式传递。 如果在处理当前主体的请求之后注意清除线程,以这种方式使用ThreadLocal是非常安全的。 当然,Spring Security会自动为您解决这个问题,因此无需担心。 某些应用程序并不完全适合使用`ThreadLocal`,因为它们使用线程的特定方式。 例如,Swing客户端可能希望Java虚拟机中的所有线程都使用相同的安全上下文。 `SecurityContextHolder`可以在启动时配置策略,以指定您希望如何存储上下文。 对于独立应用程序,您将使用`SecurityContextHolder.MODE_GLOBAL`策略。 其他应用程序可能希望安全线程生成的线程也采用相同的安全标识。 这是通过使用`SecurityContextHolder.MODE_INHERITABLETHREADLOCAL`实现的。 您可以通过两种方式从默认的`SecurityContextHolder.MODE_THREADLOCAL`更改模式。 第一个是设置系统属性,第二个是在`SecurityContextHolder`上调用静态方法。 大多数应用程序不需要更改默认值,但如果这样做,请查看JavaDoc for `SecurityContextHolder`以了解更多信息。 ## 获取有关当前用户的信息 在`SecurityContextHolder`中,我们存储当前与应用程序交互的主体的详细信息。 Spring Security使用`Authentication`对象来表示此信息。 您通常不需要自己创建`Authentication`对象,但用户查询`Authentication`对象是相当常见的。 您可以使用以下代码块(从应用程序的任何位置)获取当前经过身份验证的用户的名称,例如: ~~~ Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); if (principal instanceof UserDetails) { String username = ((UserDetails)principal).getUsername(); } else { String username = principal.toString(); } ~~~ 调用`getContext()`返回的对象是`SecurityContext`接口的一个实例。 这是保存在线程本地存储中的对象。 正如我们将在下面看到的,Spring Security中的大多数身份验证机制都会返回`UserDetails`的实例作为主体。