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 数据
相关推荐
学长毕设2 小时前
基于SpringBoot的实验室资产管理系统
java·spring boot·后端
C^h2 小时前
c++ string
开发语言·c++
raindayinrain2 小时前
c++高性能--原子操作,无锁编程,操作顺序
开发语言·c++·性能优化
学逆向的2 小时前
C++ 合并命名空间
开发语言·c++·网络安全
Zhao-Jichao2 小时前
VS2026 打包 C++ 程序生成 EXE,借助 Installer Project 扩展工具
开发语言·c++
zzu123zsw3 小时前
从臃肿的模板调用到声明式契约:深入 UniHttp 动态代理与多渠道生命周期扩展
java·spring boot·microsoft·unihttp
学逆向的3 小时前
C 局部静态变量
c语言·开发语言·网络安全
大都督会赢的4 小时前
C++第一节课
开发语言·c++
“AI国潮设计-小江”4 小时前
【AIGC实战】Python+Stable Diffusion打造“英歌舞财神”IP,解锁“马到成功”等爆款情绪营销文案设计
开发语言·人工智能·python·prompt·aigc
源码集结号4 小时前
云诊所门诊系统源码,基于SpringBoot+Vue.js架构,支持多租户设计与Docker容器化部署
java·spring boot·源码·医院信息系统·门诊系统·诊所系统