今天在开发中,碰到一个问题,有一个业务需要保存update的操作到记录表,这个时候开了异步去完成这个插入到操作记录表的动作,然后需要记录操作人,但是去security框架拿用户id的时候发现拿不到。 后来查了发现Spring Security 中想要获取登录用户信息,不能在子线程中获取,只能在当前线程中获取,其中一个重要的原因就是 SecurityContextHolder 默认将用户信息保存在 ThreadLocal 中。

但是实际上 SecurityContextHolder 一共定义了三种存储策略:

public class SecurityContextHolder {
 public static final String MODE_THREADLOCAL = "MODE_THREADLOCAL";
 public static final String MODE_INHERITABLETHREADLOCAL = "MODE_INHERITABLETHREADLOCAL";
 public static final String MODE_GLOBAL = "MODE_GLOBAL";
    ...
    ...
}

第二种存储策略 MODE_INHERITABLETHREADLOCAL 就支持在子线程中获取当前登录用户信息,而 MODE_INHERITABLETHREADLOCAL 的底层使用的就是 InheritableThreadLocal,那么 InheritableThreadLocal 和 ThreadLocal 有什么区别呢?为什么它就可以支持从子线程中获取数据呢?今天松哥就来和大家聊一聊这个话题。这个问题搞懂了,就理解了为什么在 Spring Security 中,只要我们稍加配置,就可以在子线程中获取到当前登录用户信息。