spring boot 8

一、登录认证拦截器实现

1. 核心目标

  • 所有接口统一校验 Authorization 请求头中的 JWT 令牌
  • 放行 /user/login/user/register 接口,无需令牌即可访问

2. 拦截器代码(LoginInterceptor.java

java

运行

复制代码
@Component
public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 1. 获取请求头中的令牌
        String token = request.getHeader("Authorization");
        try {
            // 2. 解析并验证令牌
            Map<String, Object> claims = JwtUtil.parseToken(token);
            // 3. 将用户信息存入 ThreadLocal,供后续业务使用
            ThreadLocalUtil.set(claims);
            // 4. 校验通过,放行请求
            return true;
        } catch (Exception e) {
            // 令牌无效/过期,设置响应状态码并拒绝请求
            response.setStatus(401);
            return false;
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 请求结束后,清除 ThreadLocal 数据,防止内存泄漏
        ThreadLocalUtil.remove();
    }
}

3. 注册拦截器(WebConfig.java

java

运行

复制代码
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                // 拦截所有请求
                .addPathPatterns("/**")
                // 放行登录、注册接口
                .excludePathPatterns("/user/login", "/user/register");
    }
}

二、ThreadLocal 工具类实现

1. 核心作用

  • 提供线程局部变量,同一请求的所有层级(Controller/Service/Mapper)都能安全访问用户信息
  • 线程安全,用完必须调用 remove() 释放数据,避免内存泄漏

2. 工具类代码(ThreadLocalUtil.java

java

运行

复制代码
public class ThreadLocalUtil {
    // 提供 ThreadLocal 对象
    private static final ThreadLocal THREAD_LOCAL = new ThreadLocal();

    // 根据键获取值
    public static <T> T get() {
        return (T) THREAD_LOCAL.get();
    }

    // 存储键值对
    public static void set(Object value) {
        THREAD_LOCAL.set(value);
    }

    // 清除 ThreadLocal,防止内存泄漏
    public static void remove() {
        THREAD_LOCAL.remove();
    }
}

三、业务接口改造(获取用户信息)

1. Controller 层接口

java

运行

复制代码
@GetMapping("/userInfo")
public Result<User> userInfo() {
    // 从 ThreadLocal 中获取解析后的用户信息
    Map<String, Object> claims = ThreadLocalUtil.get();
    String username = (String) claims.get("username");
    
    // 调用 Service 查询用户信息
    User user = userService.findByUsername(username);
    return Result.success(user);
}

2. 复用 Service & Mapper 层

  • UserService.findByUsername(username):直接复用注册 / 登录时的查询方法
  • UserMapper.select * from user where username = ?:复用已有的查询 SQL

四、关键注意事项

  1. 拦截器放行配置/user/login/user/register 必须放行,否则用户无法登录获取令牌
  2. ThreadLocal 内存泄漏 :请求结束后必须调用 remove(),否则 Tomcat 线程复用会导致数据混乱
  3. 令牌校验失败处理 :拦截器中校验失败直接返回 401 状态码,前端可据此跳转登录页
  4. 请求头名称统一 :前后端约定令牌都放在 Authorization 请求头中,避免出现字段名不一致的问题

五、完整流程总结

  1. 用户登录成功,后端生成 JWT 令牌返回给前端
  2. 前端后续请求携带令牌,请求头 Authorization: 令牌
  3. LoginInterceptor 拦截请求,解析验证令牌,将用户信息存入 ThreadLocal
  4. 业务接口从 ThreadLocal 中获取用户信息,完成后续操作
  5. 请求结束,afterCompletion 中清除 ThreadLocal 数据
相关推荐
AI玫瑰助手3 小时前
Python流程控制:pass语句的作用与使用场景
开发语言·python·信息可视化
王翼鹏3 小时前
claude 配置Luma MCP 图像识别mcp
java·linux·服务器
-快乐的程序员-3 小时前
C++的md5函数
开发语言·c++
Huangjin007_3 小时前
【C++ STL篇(九)】map容器——零基础入门与核心用法精讲
开发语言·c++·算法
MacroZheng3 小时前
IDEA + 阿里 Qoder = 王炸!
java·人工智能·后端
qq_4924484463 小时前
Jmeter Transaction Controller(事务控制器) 的 TPS(每秒事务数)严格固定为 1
java·开发语言·jmeter
2401_858286113 小时前
OS74.【Linux】线程互斥(3) 线程安全、重入
linux·运维·服务器·开发语言·线程
jsl_jsl_jsl3 小时前
Java 后端基石:JVM 运行机制、内存管理与传参陷阱
java
爱喝水的鱼丶3 小时前
SAP-ABAP:数据类型与数据对象 第二篇:底层逻辑篇——数据类型的分类体系与底层存储原理
运维·开发语言·学习·sap·abap