用户登录及在线验证 04:用户后续请求验证--统一token处理

基于ThreadLocal + 拦截器的形式统一处理

拦截器(Interceptor)

  • 是一种动态拦截方法调用的机制;

  • 类似于Servlet 开发中的过滤器Filter,用于对处理器进行前置处理和后置处理。

ThreadLocal

  • 线程内部的存储类,赋予了线程存储数据的能力。

  • 线程内调用的方法都可以从ThreadLocal中获取同一个对象。

  • 多个线程中ThreadLocal数据相互隔离

1.注册拦截器

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TokenInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/user/login", "/user/loginVerification");
    }
}

2.配置拦截器

public class TokenInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        //1、获取请求头
        String token = request.getHeader("Authorization");

        //2、使用工具类,判断token是否有效
        boolean verifyToken = JwtUtils.verifyToken(token);
        //3、如果token失效,返回状态码401,拦截
        if(!verifyToken) {
            response.setStatus(401);
            return false;
        }
        //4、如果token正常可用,放行
        //解析token,获取id和手机号码,
        Claims claims = JwtUtils.getClaims(token);
        String mobile = (String) claims.get("mobile");
        Integer id = (Integer) claims.get("id");
        
        //构造User对象,存入Threadlocal
        User user = new User();
        user.setId(Long.valueOf(id));
        user.setMobile(mobile);

        UserHolder.set(user);

        return true;
    }
    
    //清空
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserHolder.remove();
    }
}

3.ThreadLocal工具类

public class UserHolder {

    private static ThreadLocal<User> tl = new ThreadLocal<User>();

    /**
     * 保存数据到线程
     */
    public static void set(User user) {
        tl.set(user);
    }

    /**
     * 获取线程中的用户信息
     */
    public static User get() {
        return tl.get();
    }


    /**
     * 从当前线程,获取用户对象的id
     */
    public static Long getUserId() {
        if (tl.get() == null) {
            return null;
        }
        return tl.get().getId();
    }

    /**
     * 从当前线程,获取用户对象的手机号码
     */
    public static String getMobile() {
        if (tl.get() == null) {
            return null;
        }
        return tl.get().getMobile();
    }

     /**
     * 移除线程中数据
     */
    public static void remove() {
        tl.remove();
    }
}
posted @ 2022-04-29 10:37  twb_QAQZ  阅读(132)  评论(0)    收藏  举报