Spring Security获取用户信息异常,多线程获取用户报错解决方式

        在Spring Security中,SecurityContextHolder 是一个中心存储点,用于存储有关当前认证用户的信息。这些信息通常包括用户名、角色、权限等。当应用程序处理安全相关的操作时,例如验证用户身份或检查用户权限,这些信息都是非常关键的。SecurityContextHolder 支持多种存储策略,这些策略决定了安全上下文如何在不同的线程之间传递。

        MODE_THREADLOCAL工作模式,默认情况下,SecurityContextHolder使用ThreadLocal机制来保存上下文信息,也就是说,只要使用者的逻辑执行都在一个线程中使用的话,其就可以在任何地方获得上下文信息。此方式也是非常适合Servlet web应用,因为对于一个请求的处理,不管经历了多少Filter,都是在一个线程中进行的。但是对于不同的servlet request,使用的线程不一定是同一个线程(有一个线程的可能性,因为可能会从线程池中拿到同一个线程)

        MODE_GLOBAL工作模式,数据保存在一个静态变量中,其存储载体是一个静态变量,可以在多线程环境下使用,但是用的比较少。

        MODE_INHERITABLETHREADLOCAL工作模式,其存储载体为InheritableThreadLocal,InheritableThreadLocal继承ThreadLocal,多了一个特性,就是在创建子进程的时候,会自动的将父进程中的数据复制到子进程中去,实现了子进程能够获取父进程数据的功能。

        所以,如果使用的是Spring Security 5.0及以上版本,且需要在异步线程获取用户信息的时候,可以考虑修改SecurityContextHolder的默认策略。

        需要注意的是,SecurityContextHolder.setStrategyName 这个方法通常是在启动时被调用的,所以你应该在你的启动类或者配置类中设置这个策略。

        在Spring Boot应用中,如果程序是以jar包的方式运行,你可以在主类中设置这个策略:

@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
    	SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
        SpringApplication.run(MyApplication.class, args);
    }
}

或者,如果你使用的是配置类,你可以在配置类中设置策略:

import javax.annotation.PostConstruct;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.context.annotation.Configuration;

/**
 * Spring Security配置
 */
@Configuration
public class SpringSecurityConfig {

    /**
     * 项目启动时,初始化配置:设置安全上下文(SecurityContext)的存储策略
     */
    @PostConstruct
    public void setStrategyName(){
		SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);// 可继承的安全上下文
    }
}

这样,你就可以在应用中使用可继承的安全上下文了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值