个人技术总结
1、技术概述--SpringBoot集成JWT实现token验证
- 在需要用户登录的系统中有一个始终需要解决的问题,即用户权限认证。使用jwt(json web token)可以很好的解决这个问题。
2、技术详述
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
- 定义一个注解
UserLoginToken
(使用该注解的api需要相应权限)
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserLoginToken {
boolean required() default true;
}
- 新建一个类
tokenService
,并编写token的生成方法
public String getToken(User user) {
String token="";
token= JWT.create().withAudience(user.getId())
.sign(Algorithm.HMAC256(user.getPassword()));
return token;
}
//检查有没有需要用户权限的注解
if (method.isAnnotationPresent(UserLoginToken.class)) {
UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
if (userLoginToken.required()) {
// 执行认证
if (token == null) {
throw new RuntimeException("无token,请重新登录");
}
// 获取 token 中的 user id
String userId;
try {
userId = JWT.decode(token).getAudience().get(0);
} catch (JWTDecodeException j) {
throw new RuntimeException("401");
}
User user = userService.findUserById(userId);
if (user == null) {
throw new RuntimeException("用户不存在,请重新登录");
}
// 验证 token
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
try {
jwtVerifier.verify(token);
} catch (JWTVerificationException e) {
throw new RuntimeException("401");
}
return true;
}
}
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authenticationInterceptor())
.addPathPatterns("/**");
}
@Bean
public AuthenticationInterceptor authenticationInterceptor() {
return new AuthenticationInterceptor();
}
}
- 最后只需要在需要进行权限验证的地方加上注解@UserLoginToken就ok了
3、技术使用中遇到的问题和解决过程。
- 登录结果返回的是token信息,再从客户端发送时要在httprequest里加上token属性并赋值(值为刚刚服务器传来的token)
- 在服务器端验证时,由于token中已经包含你传入的用户信息,当你需要这些信息时可以直接从token中获得
public int getUserID(HttpServletRequest request){
String userId;
String token = request.getHeader("token");
userId = JWT.decode(token).getAudience().get(0);
return Integer.parseInt(userId);
}
4、进行总结。
- jwt的开销非常小,适合在单点登录中使用。由于他的信息经过签名,所以我们可以认为他是安全的。需要的时候还可以对jwt过期的时间进行设置
5、参考文献
SpringBoot集成JWT实现token验证