JWT
JWT(JSON Web Token)是一种用于双方之间传递安全信息的简洁的、URL安全的表示方法。它由三部分组成:头部(Header)、载荷(Payload)与签名(Signature)。
-
头部(Header):通常由两部分组成,令牌的类型(通常是JWT)和所使用的加密算法。例如:
{ "alg": "HS256", "typ": "JWT" }
-
载荷(Payload):包含了令牌的具体内容,比如用户信息。例如:
{"user":"admin"}
-
签名(Signature):头部和载荷都会被签名,以确保JWT不可篡改。签名的算法是在头部中指定的,它通常使用HS256(HMAC SHA-256)
- 当用户鉴权成功之时,会生成该用户的token存入请求头中
- 当用户访问其他模块时,需要进行鉴权,成功才能继续访问
但如果模块较多的情况下,不可能每个模块都去写鉴权,所以需要用到拦截器.
拦截器
编写拦截器,继承HandlerInterceptor接口实现preHandle方法
@Component //注册拦截器
public class LoginInterceptor implements HandlerInterceptor {
/*重写 preHandle方法*/
@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) {
/* 捕获异常之后设置响应头代码 并返回false结束*/
response.setStatus(401);
return false;
}
}
}
注册拦截器
@Configuration //注册配置类
@RequiredArgsConstructor //注入到Bean
public class WebConfig implements WebMvcConfigurer {
private final LoginInterceptor loginInterceptor; //构造器方法注入
/*重写 addInterceptors 方法 将自定义拦截器添加进去*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
/*addPathPatterns用于配置放行路径*/
registry.addInterceptor(loginInterceptor).excludePathPatterns("/login", "/register");
}
}
========================================================================
续
ThreadLocal优化
配置完拦截器后,我们在业务中会进行调用RequsetHeader中的Authorization来进行JWT的校验,那么每个方法都需要这样做的时候,都需要在参数中进行声明,并且再次在方法中解析token非常的繁琐,麻烦,于是我们是用ThreadLocal线程来进行优化
1、ThreadLocal优化:
ThreadLocal是线程安全的,每个方法进行调用,他们的内存空间都会被隔离开,所以不用担心数据混乱的现象。
使用ThreadLocalUtil类
package com.zzdream.zzblog.util;
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();
}
}
引入之后在拦截其中解析完token之后进行写入即可
try {
Map<String, Object> map = JwtUtil.parseToken(token);// 如果没成功执行就代表没有拿到令牌则会抛出异常
ThreadLocalUtil.set(map);//加上他
return true;
} catch (Exception e) {
// 捕获异常之后设置响应头代码 并返回false结束
response.setStatus(401);
return false;
}
这句代码的意思是将map写入到ThreadLocal中,随后每个方法在调用的时候只需要进行简单调用即可
//你的controller类或者impl类
//方法、、、、、
Map<String,Object> token = ThreadLocalUtil.get();
String username = (String) token.get("username");
return、、、、、