我在线程范围中使用spring security时有一些问题
System.out.println(((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getId());
new Thread(() -> System.out.println(((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getId())).start();
这两行应该给我当前用户ID
第一行按预期工作
第二行给我NullPointerException,因为没有当前用户它是空值
我发现了这个问题,因为我想将很多行保存到歌曲表中并且它会杀死@CreatedBy用户,这将要求线程中的当前用户并且将失败,因为这将为当前用户提供空值
答案 0 :(得分:4)
您可以将SecurityContext从一个线程转移到另一个线程
Runnable originalRunnable = new Runnable() {
public void run() {
// invoke secured service
}
};
SecurityContext context = SecurityContextHolder.getContext();
DelegatingSecurityContextRunnable wrappedRunnable =
new DelegatingSecurityContextRunnable(originalRunnable, context);
new Thread(wrappedRunnable).start();
请参阅并发支持
http://docs.spring.io/spring-security/site/docs/current/reference/html/concurrency.html
答案 1 :(得分:2)
如果您希望衍生线程继承父线程的SecurityContext
,则应设置MODE_INHERITABLETHREADLOCAL
策略。
参考SecurityContextHolder API。
请参阅this
答案 2 :(得分:0)
如果您希望所有子线程都从SecurityContextHolder
继承ThreadLocal
,则可以使用带有@PostConstruct
注释的方法进行全局设置。现在,您的子线程将可以访问相同的SecurityContextHolder。
@PostConstruct
void setGlobalSecurityContext() {
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
}
欢呼