废话不多说直接上代码,五步完成
第一步
引入依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>
第二步
JWT工具类,分别实现了【创建token】【获取用户信息】【验证用户是否修改过密码】【是否需要生成新token】
public class JwtUtil {
//加密secret
private static final String SECRET = "密钥,一定不要报漏 例如:ASD@Dik 越复杂越好";
//过期时间
private static final Integer TIME_OUT_DAY = 30;
//需要重新生成的天数 如果token的时间超过这个 则重新生成token
private static final Integer NEED_CREATE_DAY = 7;
/**
* 生成token
* @param user
* @return
*/
public static String createToken(Users user){
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE,TIME_OUT_DAY);
String token = JWT.create()
.withClaim("userId", user.getId())
.withClaim("key", DigestUtils.md5DigestAsHex(user.getPassword().getBytes()))
.withExpiresAt(calendar.getTime())
.sign(Algorithm.HMAC256(SECRET));
return token;
}
/**
* 获取token信息 如果token有误则返回null
* @param token
* @return
*/
public static DecodedJWT getTokenInfo(String token){
try {
return JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
}catch (Exception e){
return null;
}
}
/**
* 获取用户ID
* @param decodedJWT
* @return
*/
public static Integer getUserId(DecodedJWT decodedJWT){
return decodedJWT.getClaim("userId").asInt();
}
/**
* 验证是否修改过密码
* @param decodedJWT
* @param users
* @return
*/
public static boolean isUpdatedPassword(DecodedJWT decodedJWT,Users users){
String oldPwd = decodedJWT.getClaim("key").asString();
String newPwd = DigestUtils.md5DigestAsHex(users.getPassword().getBytes());
return oldPwd.equals(newPwd)?false:true;
}
/**
* 是否需要重新生成token (为了延续token时长)
* @param decodedJWT
* @return
*/
public static boolean needCreate(DecodedJWT decodedJWT){
Date timeoutDate = decodedJWT.getExpiresAt();
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE,TIME_OUT_DAY - NEED_CREATE_DAY);
if(timeoutDate.before(calendar.getTime())){
return true;
}
return false;
}
}
第三步
自定义个注解,用来标注哪些方法是需要验证token的
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedLogin {
}
第四步
创建一个拦截器
@Component
public class UserLoginInterceptor implements HandlerInterceptor {
@Autowired
UsersService usersService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String token = request.getHeader("token");
// 如果不是映射到方法直接通过
if(!(handler instanceof HandlerMethod)){
return true;
}
HandlerMethod handlerMethod=(HandlerMethod)handler;
Method method=handlerMethod.getMethod();
//检查是否有NeedLogin注释
if (method.isAnnotationPresent(NeedLogin.class)) {
DecodedJWT tokenInfo = JwtUtil.getTokenInfo(token);
if(token!=null && tokenInfo!=null){
Users user = usersService.getById(JwtUtil.getUserId(tokenInfo));
//验证是否修改过密码
if(!JwtUtil.isUpdatedPassword(tokenInfo,user)){
//如果需要重新创建一个token 则通知客户端保存新的toekn 并且将新的token返回
if(JwtUtil.needCreate(tokenInfo)){
JSONObject tokenJson = new JSONObject();
tokenJson.put("token",JwtUtil.createToken(user));
result(response,Result.success(tokenJson));
return false;
}else{
return true;
}
}
}
//验证未通过
result(response,Result.failure("token_error"));
return false;
}
return true;
}
private void result(HttpServletResponse response,Result result){
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
response.setStatus(200);
PrintWriter out = null;
try {
out = response.getWriter();
out.append(JSON.toJSONString(result));
} catch (IOException e) {
e.printStackTrace();
}finally {
if(out!=null)
out.close();
}
}
}
第五步
配置拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Resource
private UserLoginInterceptor userLoginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(userLoginInterceptor)
.addPathPatterns("/user/**");//这是你的拦截地址
}
}
大功告成 用就可以了