SpringBoot+JWT Token验证

1. pom.xml 添加依赖

1
2
3
4
5
 <dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.1</version>
</dependency>

2. application.yml

1
2
3
jwt:
expire: 86400000 #jwt有效时间(24小时)
secret: secret # 签名密钥

3. 工具类生成、验证token、根据token提取用户ID

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class JwtUtil {

//token有效时长
private static long EXPIRE_TIME;
//密钥
private static String SECRET;

@Value("${jwt.secret}")
public void setSecret(String secret) {
JwtUtil.SECRET= secret;
}

@Value("${jwt.expire}")
public void setExpireTime(long date) {
JwtUtil.EXPIRE_TIME= date;
}

/**
* 生成签名,24小时后过期
* @param userId
* @return
*/
public static String getToken(String userId) {
try {
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
Algorithm algorithm = Algorithm.HMAC256(SECRET);
return JWT.create()
// 将 user id 保存到 token 里面
.withAudience(userId)
.withExpiresAt(date)
// token 的密钥
.sign(algorithm);
} catch (Exception e) {
return null;
}
}

/**
* 根据token获取userId
* @param token
* @return
*/
public static String getUserName(String token) {
try {
String userId = JWT.decode(token).getAudience().get(0);
return userId;
} catch (JWTDecodeException e) {
return null;
}
}

/**
* 校验token
* @param token
* @return
*/
public static DecodedJWT verify(String token){
JWTVerifier build = JWT.require(Algorithm.HMAC256(SECRET)).build();
return build.verify(token);
}

}

4. 添加拦截器

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
35
36
37
38
39
40
41
public class JwtInterceptor implements HandlerInterceptor {

@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) {
//OPTIONS请求默认通过
if (httpServletRequest.getMethod().equals("OPTIONS")){
return true;
}
//获取请求头X-Token字段
String token = httpServletRequest.getHeader("X-Token");
try {
JwtUtil.verify(token);
}catch (SignatureVerificationException e){
//e.printStackTrace();
System.out.println("无效签名");
return false;
}catch (TokenExpiredException e){
//e.printStackTrace();
System.out.println("token过期");
return false;
}catch (AlgorithmMismatchException e){
//e.printStackTrace();
System.out.println("token算法不一致");
return false;
}catch (Exception e){
//e.printStackTrace();
System.out.println("token无效");
return false;
}
return true;
}

@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

}
}

5. 配置拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class InterceptorConfig  implements WebMvcConfigurer {

@Override
public void addInterceptors(InterceptorRegistry registry) {

registry.addInterceptor(new JwtInterceptor())
//拦截的路径
.addPathPatterns("/**")
//排除登录接口
.excludePathPatterns("/prod-api/user/login")
.excludePathPatterns("/prod-api/user/logout");
WebMvcConfigurer.super.addInterceptors(registry);

}
}

6. controller层实现登录方法和获取用户信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RequestMapping(value = "/login",method = RequestMethod.POST)
public Result<JSONObject> login(@RequestBody String userInfo){
JSONObject jsonObject = JSON.parseObject(userInfo);
String username = (String) jsonObject.get("username"); //获取登录账号
String password = (String) jsonObject.get("password"); //登录密码

/*
* 验证用户密码是否正确(此处省略)
*/

JSONObject dataJson = new JSONObject();
dataJson.put("token",JwtUtil.getToken(username)); //将生成token发送至用户
return Result.success("登录成功", dataJson);
}

7. 测试

登录成功返回token

更改请求x-token,被拦截器拦截返回错误信息

源码

SpringBoot+JWT Token验证