ThreadLocal获取用户信息

一般在前后端分离项目中,我们都是通过token去获取用户信息,然后这样我感觉不够骚气,刚好偶然一次机会一个朋友告诉了我他们那如何设计处理的。大致处理如下,使用的时候,直接获取即可。

import org.springframework.stereotype.Component;

import com.spring.framework.entity.SysUserEntity;

import java.util.Optional;

/**
 * @author ljw
 * 2021年6月19日17:04:083
 */
@Component
public class DataContextSupport {

    public static final ThreadLocal<SysUserEntity> dataContext = new ThreadLocal<>();

    private static final SysUserEntity DATA_PERMISSIONS = new SysUserEntity();

    /**
     * 设置当前用户数据权限
     */
    public static void setDataPermissions(SysUserEntity dataPermissions) {
        dataContext.set(dataPermissions);
    }

    /**
     * 获取当前用数据权限
     */
    public static SysUserEntity getDataPermissions() {
        return Optional.ofNullable(dataContext.get()).orElse(DATA_PERMISSIONS);
    }

    /**
     * 移除当前用户数据权限
     */
    public static void close() {
        dataContext.remove();
    }

}

定义一个过滤器,每次请求完之后把对应的用户信息存放起来,由于我使用的是shiro,刚好可以直接利用shiro的tokenFilter,于是我就在userRealm认证成功之后放入,效果类似。

@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
		JwtToken jwtToken = (JwtToken)authenticationToken;
		String token = (String) jwtToken.getPrincipal();
		//token是否存在
		if (StringUtils.isEmpty(token)||!token.startsWith("Bearer")) {
            throw new AuthenticationException(" 非法请求,请先登录! ");
        }
		token = token.replace("Bearer ", "");
		//token是否有效
		String username = JwtUtil2.getUsername(token);
		String random = JwtUtil2.getUuid(token);
		if(StringUtils.isEmpty(username)||StringUtils.isEmpty(random)) {
			throw new AuthenticationException(" 认证无效,请重新认证! ");
		}
		//验证token是否合法
		if(!JwtUtil2.verify(token, username,random)) {
			throw new AuthenticationException(" 认证无效,请重新认证! ");
		}
		LoginUser loginUser = (LoginUser) redisUtil.get("LOGIN"+username);
		if(loginUser==null) {
			throw new AuthenticationException(" 登录过期,请重新登录! ");
		}
		if(!loginUser.getUuid().equals(random)) {
			throw new AuthenticationException(" 在别处登录,请重新登录! ");
		}
		redisUtil.expire("LOGIN" + username, 60 * 30);
		DataContextSupport.setDataPermissions(loginUser.getSysUserEntity());//将用户信息存入
		return new SimpleAuthenticationInfo(loginUser.getSysUserEntity(),jwtToken.getPrincipal(),getName());
	}

为了避免内存泄漏问题,我们可以在每次请求执行完 之后释放掉。
定义拦截器

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
 * 释放资源
 * @author ljw
 *
 */
public class DataContextInterceptor implements  HandlerInterceptor  {

    /**
     * 拦截前
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }
 
   
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }
 
    /**
     * 拦截后
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    	DataContextSupport.close();
    }
}

新增配置类,让拦截器生效

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import com.spring.framework.user.DataContextInterceptor;

@Configuration
public class WebMvcConfigurer implements org.springframework.web.servlet.config.annotation.WebMvcConfigurer {

	 //添加拦截器
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new DataContextInterceptor()).addPathPatterns("/**")  ;
    }
}

测试效果
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值