springboot3中token的颁发及使用拦截器实现请求前的token拦截校验

本文介绍了如何在SpringBoot项目中通过pom.xml添加JWT生成依赖,创建工具类实现token的颁发和校验,使用ThreadLocal存储用户信息,并在interceptor中实现基于JWT的身份校验拦截器,以及在config中配置应用这些拦截器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 在配置文件pom.xml中添加jwt生成依赖

      <dependency>
          <groupId>com.auth0</groupId>
          <artifactId>java-jwt</artifactId>
          <version>4.4.0</version>
      </dependency>
  1. 在utils包下创建一个jwtUtil的工具类实现token的统一颁发及校验
package org.example.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;

import java.util.Date;
import java.util.Map;

public class JwtUtil {

    private static final String KEY = "xuanmao";//设置密钥(要想非对称加密这里换成私钥)
  
  //接收业务数据,生成token并返回
    public static String genToken(Map<String, Object> claims) {
        return JWT.create()
                .withClaim("claims", claims)//token中加入用户信息
                .withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 12))//设置超时时间
                .sign(Algorithm.HMAC256(KEY));//设置加密类型及密钥
    }

  //接收token,验证token,并返回业务数据
    public static Map<String, Object> parseToken(String token) {
        //去除token的前缀标记"Bearer "
        var newToken = token.contains("Bearer ")?token.substring("Bearer ".length()):token;
        return JWT.require(Algorithm.HMAC256(KEY))//要想非对称加密这里换成公钥
                .build()
                .verify(newToken)
                .getClaim("claims")
                .asMap();
    }

}

  1. 在utils包下创建ThreadLocalUtil工具类用于将用户信息存放在ThreadLocal中,方便在方法中获取token中的信息
package org.example.utils;

import java.util.HashMap;
import java.util.Map;

/**
 * ThreadLocal 工具类
 */
@SuppressWarnings("all")
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. 在intercopters包创建拦截器实现接口响应前的身份校验
package org.example.intercopters;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.example.utils.JwtUtil;
import org.example.utils.ThreadLocalUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.Map;

@Component //注册拦截器 将其放入ioc容器中
public class LoginInterceptor implements HandlerInterceptor {
    //创建登录身份校验拦截器
    @Override  //请求开始前触发的拦截方法
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //令牌验证
        String token = request.getHeader("Authorization");
        try {
            Map<String, Object> claims = JwtUtil.parseToken(token);

            //把用户信息存储到ThreadLocal中,tomcat会在每次接口请求时创建一个线程 
            //而ThreadLocal中存储的数据是线程安全的
            ThreadLocalUtil.set(claims);

            //放行
            return true;

        } catch (Exception e) {
            //设置响应状态码
            response.setStatus(401);
            //设置响应字符集和响应内容
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html; charset=UTF-8");
            String errorMessage = "未登录";
            response.getWriter().write("{\"error\": \"" + errorMessage + "\"}");
            //不放行
            return false;
        }
    }
    
    @Override  //请求完成后触发的拦截方法
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //清空ThreadLocal中的数据防止内存泄漏
        ThreadLocalUtil.remove();
    }
}

  1. 在config包下创建配置类并在配置类中使用拦截器
package org.example.config;

import org.example.intercopters.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration  //把配置类添加到ioc容器中
public class WebConfig implements WebMvcConfigurer {

    @Autowired //注入ioc容器中的LoginIntercopter拦截器
    private LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //登录和注册接口不拦截
        registry.addInterceptor(loginInterceptor).excludePathPatterns("/user/login", "/user/register");
    }
}

端代码实现: 1. 登录成功后,将JWT Token存储在本地存储(LocalStorage)中: ```javascript localStorage.setItem(&#39;jwtToken&#39;, response.data.token); ``` 2. 在每次请求后端接口时,将JWT Token携带在请求头中: ```javascript axios.defaults.headers.common[&#39;Authorization&#39;] = &#39;Bearer &#39; + localStorage.getItem(&#39;jwtToken&#39;); axios.get(&#39;/api/userInfo&#39;) .then(response => { // 处理响应数据 }) .catch(error => { // 处理错误信息 }); ``` 3. 后端返回401 Unauthorized错误时,端可以跳转到登录页重新登录: ```javascript axios.interceptors.response.use( response => response, error => { if (error.response.status === 401) { // 跳转到登录页 window.location.href = &#39;/login&#39;; } return Promise.reject(error); } ); ``` 后端代码实现: 1. 编写JWT Token校验拦截器: ```java public class JwtInterceptor implements HandlerInterceptor { @Autowired private JwtUtil jwtUtil; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 从请求头中获取JWT Token String token = request.getHeader("Authorization"); if (token != null && token.startsWith("Bearer ")) { token = token.substring(7); // 校验JWT Token是否有效 if (jwtUtil.validateToken(token)) { return true; } } // Token无效,返回401 Unauthorized错误 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return false; } } ``` 2.拦截器注册到拦截器链中: ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private JwtInterceptor jwtInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(jwtInterceptor) .addPathPatterns("/**") // 拦截所有请求 .excludePathPatterns("/login"); // 排除登录请求 } } ``` 3. 在Controller中处理请求: ```java @RestController public class UserController { @GetMapping("/api/userInfo") public String getUserInfo() { // 处理请求 return "User Info"; } } ``` 需要注意的是,以上代码仅为示例代码,具体实现需要根据实际情况进行调整。同时,为了提高安全性,JWT Token需要设置过期时间,并定期更新Token。在实现JWT Token校验时,可以使用axios等HTTP请求库来发送请求,并设置请求头中的Authorization字段。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值