创建 jwt 拦截与登录线程

jwt属性配置

1
2
3
4
5
6
7
8
@Component
@ConfigurationProperties(prefix = "yml文件中的配置路径")
@Data
public class JwtProperties {
private String key;
private long ttl;
private String tokenName;
}

jwt拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* jwt 拦截器
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class JwtInterceptor implements HandlerInterceptor{
private final JwtProperties jwtProperties;

@Override
public boolean preHandle(
@NonNull HttpServletRequest request, // 请求
@NonNull HttpServletResponse response, // 响应
@NonNull Object handler) { // 拦截的方法
String token = request.getHeader(jwtProperties.getTokenName());
try {
// 检验 token
var claims = JwtUtils.parseJWT(token, jwtProperties.getKey());
// 获取操作者 id
BaseContext.setCurrentId(Long.valueOf(claims.get("id").toString()));
return true;
} catch (SignatureVerificationException e) {
throw new UnauthorizedException("无效签名");
} catch (TokenExpiredException e) {
throw new UnauthorizedException("token过期");
} catch (AlgorithmMismatchException e) {
throw new UnauthorizedException("token算法不一致");
} catch (SignatureException e) {
throw new ForbiddenException("签名错误");
} catch (Exception e) {
throw new ServerErrorException("未知 jwt 拦截错误 " + e.getMessage());
}
}
}

WebMvcComfig中注册拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 注册自定义拦截器
* 配置多端项目时,每一端都要进行相应拦截
*
* @param registry InterceptorRegistry
*/
protected void addInterceptors(InterceptorRegistry registry) {
log.info("注册 jwt 拦截器...");
registry.addInterceptor(jwtInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/admin/login")
.excludePathPatterns("/user/login");
}

构建jwt登录线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 基于ThreadLocal封装工具类, 用户保存和获取当前登录用户id
*/
public class BaseContext {
private static final ThreadLocal<Long> threadLocal = new ThreadLocal<>();
public static void setCurrentId(Long id){
threadLocal.set(id);
}
public static Long getCurrentId(){
return threadLocal.get();
}
public static void removeCurrentId() {
threadLocal.remove();
}
}