弹簧安全当前用户的线程

时间:2017-02-20 10:08:07

标签: spring multithreading spring-security

我在线程范围中使用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用户,这将要求线程中的当前用户并且将失败,因为这将为当前用户提供空值

3 个答案:

答案 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);
}

欢呼