一、问题描述
SecurityContextHolder.getContext()获取不到Security上下文数据?
二、原因
我的项目中出现这个问题是由于使用了异步线程(如下),导致Security上下文无法从主线程传递到异步线程中。
threadPoolTaskExecutor.execute(()->{
// ...
SecurityContext context = SecurityContextHolder.getContext();
// ...
})
三、解决方案
1. 修改SpringSecurity的安全策略(不推荐)
# 修改配置(在这种模式下,安全上下文信息存储在当前线程的 InheritableThreadLocal 中,可以被该线程创建的子线程继承和共享。默认是MODE_THREADLOCAL)
spring.security.strategy=MODE_INHERITABLETHREADLOCAL
不推荐原因:
在使用 MODE_INHERITABLETHREADLOCAL 安全策略时,您需要小心处理多线程环境下的安全性问题,以避免出现数据竞争、死锁等问题。同时,这种模式可能会对应用程序的性能产生一定的影响,因为它需要通过序列化和反序列化来传递安全上下文信息。因此,在使用 MODE_INHERITABLETHREADLOCAL 安全策略时需要小心,确保在必要的情况下使用它,以避免性能问题。
2. 使用DelegatingSecurityContextRunnable在异步线程中正确地传递 Spring Security 上下文信息。如下
threadPoolTaskExecutor.execute(new DelegatingSecurityContextRunnable(() -> {
// ...
SecurityContext context = SecurityContextHolder.getContext();
// ...
})