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 数据
相关推荐
java资料站1 分钟前
二、Spring AI Alibaba · ChatModel
java·windows·spring
半杯咖啡半行码15 分钟前
C++ 编程与 STL 模板:从泛型编程到内存安全详解
开发语言·c++
十年Java程序媛25 分钟前
Java 接口和抽象类对比|Java8 新特性,抛弃老旧八股,正确选型
java·spring boot·后端
caoerzhong27 分钟前
JeeWMS 开源 WMS 部署避坑指南:Java 仓库管理系统的环境基线、四类根因与可复现交付
java·开发语言·开源
用户37215742613528 分钟前
Java 合并 PDF 文件:完整合并、指定页面合并与流合并
java
时间的拾荒人30 分钟前
Qt 界面优化:绘图详解 —— 从基础图形到图片处理
开发语言·qt·面试
MayZork1 小时前
Qt 文件操作:QSaveFile 与 QTemporaryFile(含 QTemporaryDir)实战
开发语言·qt
北冥you鱼1 小时前
Go 语言空接口(interface{})使用场景与最佳实践
开发语言·windows·golang
for_ever_love__1 小时前
MySQL 全文索引实战:FULLTEXT、ngram 中文分词与 MATCH AGAINST 到底该怎么用
java·python·mysql·全文检索·分词·索引·ngram
java资料站1 小时前
五、Spring AI Alibaba · Memory · Saver(短期会话)
java·spring·microsoft