问题:
我们用用异步线程的时候不能把SpringSecurity当前用户信息context带到子线程。
为了方便,我们需要进行信息透传
解决方法
-
需要加个参数 -Dspring.security.strategy=MODE_INHERITABLETHREADLOCAL
-
或者增加代码块
-
static { SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL); }
-
如果使用了线程池,则添加如下配置
@Bean
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(50);
executor.setQueueCapacity(25);
executor.setThreadNamePrefix("async-");
return executor;
}
@Bean
public DelegatingSecurityContextAsyncTaskExecutor taskExecutor(ThreadPoolTaskExecutor delegate) {
return new DelegatingSecurityContextAsyncTaskExecutor(delegate);
}
为什么要添加线程池
如果用的是线程池的话,子线程每次使用完,以前被赋值的用户context不会被清理掉。而且下次再调用这个子线程的时候也不会重新设置当前父线程的用户上下文。
所以要给异步线程加个DelegatingSecurityContextAsyncTaskExecutor
其他
Spring-web中的上下文传递方式:
//主线程中获取上下文内容
RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
//子线程中设置上下文内容
RequestContextHolder.setRequestAttributes(attributes);