一、什么是jjwt?jwt怎么生成token?
JWT实现token机制_java jwt token_java-zh的博客-CSDN博客
二、什么是ThreadLocal?
ThreadLocal详解-CSDN博客
三、准备的jar
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.0</version>
        </dependency>
         <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.75</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.14</version>
        </dependency> 
四、代码实现
ThreadLocalUtils工具类
import java.util.HashMap;
import java.util.Map;
/**
 * @author zhong
 * @describe 线程池缓存工具
 * @date 2023/11/16 10:55
 */
public class ThreadLocalUtils {
    private static ThreadLocal<Map<String, Object>> threadLocal = new ThreadLocal<Map<String, Object>>();
    /**
     * 向ThreadLocal缓存值
     *
     * @param key   要缓存的KEY
     * @param value 要缓存的VALUE
     */
    public static void set(String key, Object value) {
        if (!isCaheIsNull()) {
            threadLocal.get().put(key, value);
        } else {
            Map<String, Object> vmap = new HashMap<>();
            vmap.put(key, value);
            threadLocal.set(vmap);
        }
    }
    /**
     * 从ThreadLocal里获取缓存的值
     *
     * @param key 要获取的数据的KEY
     * @return 要获取的值
     */
    public static Object getCache(String key) {
        Map<String, Object> map = threadLocal.get();
        if (isCaheIsNull()) {
            return null;
        }
        if (map.containsKey(key)) {
            return map.get(key);
        } else {
            return null;
        }
    }
    /**
     * 根据KEY移除缓存里的数据
     *
     * @param key
     */
    public static void removeByKey(String key) {
        if (isCaheIsNull()) {
            return;
        } else {
            threadLocal.get().remove(key);
        }
    }
    /**
     * 移除当前线程缓存
     * 用于释放当前线程threadlocal资源
     */
    public static void remove() {
        threadLocal.remove();
    }
    private static boolean isCaheIsNull() {
        return threadLocal.get() == null;
    }
} 
jjwt实现的工具类在上面的文章有写,这里就不写了
实体类
@Data
@Accessors(chain = true)
public class UserTest {
    /**
     * 用户id
     */
    private Long userId;
    /**
     * 用户名称
     */
    private String userName;
    /**
     * 年龄
     */
    private Integer age;
    /**
     * 角色id
     */
    private Integer roleId;
} 
拦截器配置
@Configuration
public class LoginConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册TestInterceptor拦截器
        InterceptorRegistration registration = registry.addInterceptor(loginInterceptor);
        registration.addPathPatterns("/**");//所有路径都被拦截
        registration.excludePathPatterns( // 添加不拦截路径
                "/base/getToken"
        );
    }
} 
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("token");
        if(StringUtils.isEmpty(token)){
            return false;
        }
        Map<String, Object> stringObjectMap = JWTUtil.extractInfo(token, "user:login");
        if(CollectionUtils.isEmpty(stringObjectMap)){
            return false;
        }
        UserTest loginUser = new UserTest();
        loginUser.setRoleId((Integer) stringObjectMap.get("roleId"));
        loginUser.setUserId(Long.valueOf(stringObjectMap.get("userId")+""));
        loginUser.setUserName((String) stringObjectMap.get("userName"));
        ThreadLocalUtils.set("userInfo",loginUser);
        //刷新token过期时间
        Date ecpiration = new Date(System.currentTimeMillis() + 6000000L);
        Jwts.builder().setExpiration(ecpiration);
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        // TODO Auto-generated method stub
    }
    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        // TODO Auto-generated method stub
    }
} 
controller实现
@RestController
@RequestMapping("/base")
public class TestController {
    @GetMapping("/getToken")
    public String getToken() throws Exception {
        UserTest userTest = new UserTest().setUserId(134288L).setUserName("zhong").setAge(10).setRoleId(2);
        //转成map
        Map<String, Object> map = (Map) JSON.parse(JSON.toJSONString(userTest));
        String token = JWTUtil.generateToken(map, "user:login");
        ThreadLocalUtils.set("token", token);
        System.out.println("生成token");
        return token;
    }
    @GetMapping("/checkToken")
    public String checkToken() {
        UserTest userTest = (UserTest) ThreadLocalUtils.getCache("userInfo");
        // 获取完值以后,进行移除
        ThreadLocalUtils.removeByKey("userInfo");
        return JSON.toJSONString(userTest);
    }
} 
五、测试
5.1 生成token
        这里的data信息就是返回的token信息,因为这里配置了代码返回的格式,所以返回的内容在data里面,参考文档:springboot的@RestControllerAdvice作用和捕获自定义异常返回自定义结果案例-CSDN博客
5.2 token解析
解析的内容为token加密的内容

![BUUCTF--[ACTF2020 新生赛]Include](https://img-blog.csdnimg.cn/a972a4d7f8d94215bc4f00f0991c4536.png)


















