JWT
注意第二部分不要有密码等敏感信息


生成JWT令牌后,怎么使用呢?笨方法就是给每个需要认证的方法加上验证。现在流行的方法是建立拦截器,分为两个部分:
一:写拦截器-建立防止拦截器的包-创建拦截器类-写拦截器:
package com.example.interceptors;
import com.example.pojo.Result;
import com.example.utils.JwtUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
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> map = JwtUtil.parseToken(token);
//放行
return true;
} catch (Exception e) {
//设置响应状态码 HttpServletResponse response
response.setStatus(401);
//不放行
return false;
}
}
}
二、注册拦截器:创建config包,在里面创建相应类-注册拦截器:
package com.example.config;
import com.example.interceptors.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
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//登录和注册接口不拦截
registry.addInterceptor(loginInterceptor).excludePathPatterns("/user/login","/user/register");
}
}
怎么用token里的信息?以查询用户信息为例:
@GetMapping("/userInfo")
public Result<User> userInfo(@RequestHeader(name = "Authorization") String token) {
Map <String,Object> map = JwtUtil.parseToken(token);//解析token
//注意这里返回的是Map,能够直接把 JSON 格式的数据映射到 Java 的数据结构中,
//返回 Map 后,可以灵活地获取各种声明信息。例如:Date issuedAt = (Date) map.get("iat");// 获取签发时间
String username = (String) map.get("username");
User user = userService.findByUserName(username);
return Result.success(user);
}
注意,我们已经写好了拦截器,但是上面的代码又自己解析了token,其实是多余的,那么怎么复用呢?
答案是:THreadLocal


注:线程执行顺序随机的
如何使用?
首先添加工具类:
package com.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();
}
}
然后在拦截器中创立ThreadLocal对象
@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> map = JwtUtil.parseToken(token);
//把业务数据放入TheadLocal中
ThreadLocalUtil.set(map);
//放行
return true;
} catch (Exception e) {
//设置响应状态码 HttpServletResponse response
response.setStatus(401);
//不放行
return false;
}
}
}
然后Controller的方法就可以简化了:
@GetMapping("/userInfo")
public Result<User> userInfo(/*@RequestHeader(name = "Authorization") String token*/) {
// Map <String,Object> map = JwtUtil.parseToken(token);//解析token
Map<String,Object> map =ThreadLocalUtil.get();
String username = (String) map.get("username");
User user = userService.findByUserName(username);
return Result.success(user);
}
}
为防止内存泄漏,还应该在拦截器中加入afterCompletion方法,拦截器完整代码为:
package com.example.interceptors;
import com.example.pojo.Result;
import com.example.utils.JwtUtil;
import com.example.utils.ThreadLocalUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
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> map = JwtUtil.parseToken(token);
//把业务数据放入TheadLocal中
ThreadLocalUtil.set(map);
//放行
return true;
} catch (Exception e) {
//设置响应状态码 HttpServletResponse response
response.setStatus(401);
//不放行
return false;
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//清空ThreadLocal中的数据,防止内存泄漏
ThreadLocalUtil.remove();
}
}
2093

被折叠的 条评论
为什么被折叠?



