Threadlocal的应用

文章介绍了如何在SpringSecurity项目中自定义过滤器TokenAuthenticationFilter,解析JWT并使用ThreadLocal的UserContext来存储用户认证信息,以便在Controller层方便地访问和使用这些信息,避免重复解析JWT,提高性能。
摘要由CSDN通过智能技术生成

springsecurity中通过线程上下文存储认证信息

在我的个人博客项目中引入了springsecurity做认证授权处理,但是springsecurity原生内置的认证过滤器基本上是跟登录操作强绑定的,也就是UsernamePasswordAuthenticationFilter
每次请求都需要输入用户名和密码才能进行认证,而我项目中采用jwt保存登录状态来进行认证,所以我们自定义一个public class TokenAuthenticationFiliter extends OncePerRequestFilter过滤器
然后通过
http.addFilterBefore(new TokenAuthenticationFiliter(), UsernamePasswordAuthenticationFilter.class)
将其添加到UsernamePasswordAuthenticationFilter过滤器的前面
在TokenAuthenticationFiliter 中我们进行token解析之后,将提取出来的用户名和权限信息存入UsernamePasswordAuthenticationToken中,然后将UsernamePasswordAuthenticationToken存入SecurityContextHolder所持有的SecurityContext中,存入当前线程上下文,以供后续过滤器使用,而无需多次解析jwt影响性能

将从jwt中提取的信息存入自定义的UserContext中

springsecurity的整个 过滤器链对于后续springmvc中的handler方法是不可见的,在security的过滤器链中解析的token信息我们有必要存入线程上下文,以方便controller层的方法去获取这些信息进行相关处理
所以这里我们先自定义一个接口UserContext


public interface UserContext extends Serializable {
    MyUserVO getMyUserVO();
    // 对用户进行赋值的方法
    void setCurrentUserVO(MyUserVO myUserVO);

    // 获取变量
    Object getProperty(Object var);

    // 添加变量
    void addProperty(Object varKey, Object varValue);

    // 移出变量
    void removeProperty(Object var);

    // 获取所有变量
    Map<Object, Object> getProperties();

    // 初始化变量
    void setProperties(Map<Object, Object> map);

    // 移出所有变量
    void removeAllProperties();

    // 添加业务变量
    void addBusiProperty(Object busiVarKey, Object busiVarValue);

    // 获取业务变量
    Object getBusiProperty(Object busiVarKey);

    // 获取所有业务变量
    Map<Object, Object> getBusiProperties();

    // 初始化业务变量
    void setBusiProperties(Map<Object, Object> map);


}  

然后再定义一个类去实现它

/**
 * 用户信息的上下文信息
 */
public class UserContextImpl implements UserContext {
    private static final long serialVersionUID = 8383356012441014698L;
    // 用户类
    private MyUserVO myUserVO = new MyUserVO();
    // 变量
    private Map<Object, Object> properties = new HashMap<>();
    // 业务变量
    private Map<Object, Object> busiProperties = new HashMap<>();

    public UserContextImpl() {
    }

    @Override
    public MyUserVO getMyUserVO() {
        return this.myUserVO;
    }

    @Override
    public void setCurrentUserVO(MyUserVO myUserVO) {
        this.myUserVO = myUserVO;
    }

    @Override
    public Object getProperty(Object var) {
        return this.properties;
    }

    @Override
    public void addProperty(Object varKey, Object varValue) {
        this.properties.put(varKey, varValue);
    }

    @Override
    public void removeProperty(Object var) {
        this.properties.remove(var);
    }

    @Override
    public Map<Object, Object> getProperties() {
        return this.properties;
    }

    @Override
    public void setProperties(Map<Object, Object> map) {
        this.properties = map;
    }

    @Override
    public void removeAllProperties() {
        this.properties.clear();
    }

    @Override
    public void addBusiProperty(Object busiVarKey, Object busiVarValue) {
        this.busiProperties.put(busiVarKey, busiVarValue);
    }

    @Override
    public Object getBusiProperty(Object busiVarKey) {
        return this.busiProperties.get(busiVarKey);
    }

    @Override
    public Map<Object, Object> getBusiProperties() {
        return this.busiProperties;
    }

    @Override
    public void setBusiProperties(Map<Object, Object> map) {
        this.busiProperties = map;
    }
}

再定义一个类UserContextHolder ,并且设置一个localthread成员变量,这才是我们保存线程上下文信息的核心,spring中其实大量使用了ThreadLocal来进行上下文保存一些重要信息

/**
 * 管理存储用户信息的上下文
 */
public class UserContextHolder {


    private static final ThreadLocal<UserContext> contextHolder = new ThreadLocal<>();

    public UserContextHolder() {
    }
    public static void setContext(UserContext userContext){
        contextHolder.set(userContext);
    }
    public static UserContext getContext(){
        UserContext userContext=contextHolder.get();
        if(userContext==null){
            userContext=new UserContextImpl();
            setContext(userContext);
        }
        return userContext;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值