在spring security,用SecurityContextHolder.getContext().getAuthentication().getPrincipal()获取登录用户的信息,发现获取到的用户有串值现象——获取用户信息,发现获取到的是别人的信息,偶发性还有取值为null的情况。经同事提醒,是不是用了多线程,查到了问题的原因。
//原代码
ExecutorService executorService = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("job").build());
executorService.execute(() -> {
//获取用户对象
LoginUserDetails userDetails = (LoginUserDetails)SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
});
//改进后
ExecutorService executorService = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("job").build());
SecurityContext securityContext = SecurityContextHolder.getContext();
executorService.execute(() -> {
//把context设置进去
SecurityContextHolder.setContext(securityContext);
//获取用户对象
LoginUserDetails userDetails = (LoginUserDetails)SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
});
源码:
ThreadLocal是线程独有的局部变量,只针对当前线程,当前代码里使用了嵌套线程,子线程里的SecurityContext和父线程里的SecurityContext不是同一个,需要从父线程把SecurityContext传入到子线程