一、JWT工具类
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class JwtUtil {
/**
* 过期时间一天,
* TODO 正式运行时修改为15分钟
*/
private static final long EXPIRE_TIME = 24 * 60 * 60 * 1000;
/**
* token私钥
*/
private static final String TOKEN_SECRET = "f26e587c28064d0e855e72c0a6a0e618";
/**
* 校验token是否正确
*
* @param token 密钥
* @return 是否正确
*/
public static boolean verify(String token) {
try {
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
JWTVerifier verifier = JWT.require(algorithm)
.build();
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception exception) {
return false;
}
}
/**
* 获得token中的信息无需secret解密也能获得
*
* @return token中包含的用户名
*/
public static String getUserName(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("userName").asString();
} catch (JWTDecodeException e) {
return null;
}
}
/**
* 获取登陆用户密码
*
* @param token
* @return
*/
public static String getUserId(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("userId").asString();
} catch (JWTDecodeException e) {
return null;
}
}
/**
* 生成签名,15min后过期
*
* @param userName 用户名
* @return 加密的token
*/
public static String sign(String userName) {
try {
// 过期时间
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
// 私钥及加密算法
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
// 设置头部信息
Map<String, Object> header = new HashMap<>(2);
header.put("typ", "JWT");
header.put("alg", "HS256");
// 附带username,userId信息,生成签名
return JWT.create()
.withHeader(header)
.withClaim("userName", userName)
.withExpiresAt(date)
.sign(algorithm);
} catch (Exception e) {
return null;
}
}
}
二、 @TokenRequire注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface TokenRequired {
boolean required() default true;
}
三、 Token拦截器
public class TokenInterceptor implements HandlerInterceptor {
@Autowired
RedisUtil redisUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 从 http 请求头中取出 token
String token = request.getHeader("Token");
// 如果不是映射到方法直接通过
if (!(handler instanceof HandlerMethod)) {
return true;
}
Method method = ((HandlerMethod) handler).getMethod();
//检查有没有需要用户权限的注解
if (method.isAnnotationPresent(TokenRequired.class)) {
TokenRequired userLoginToken = method.getAnnotation(TokenRequired.class);
if (userLoginToken.required()) {
// 执行认证
if (token == null) {
ResponseUtil.responseMessage(response, InfoUtil.getInfo(UserError.TOKEN_IS_NOT_EXIT));
return false;
}
//获取token中的userId
String userId = JwtUtil.getUserId(token);
if (userId == null) {
ResponseUtil.responseMessage(response, InfoUtil.getInfo(UserError.TOKEN_IS_INVALID));
return false;
}
//验证token是否过期
if (!JwtUtil.verify(token)) {
//如果token检验失败,查询redis中是否存在,redis为空,用户重新登录
if (redisUtil.get("userToken_" + userId) == null) {
ResponseUtil.responseMessage(response, InfoUtil.getInfo(UserError.NONE_TOKEN));
return false;
}
//redis中存在token,刷新token
String refreshToken = JwtUtil.sign(userId);
redisUtil.set("userToken_" + userId, refreshToken, 20, TimeUnit.DAYS);
JSONObject jsonObject = new JSONObject();
jsonObject.put("newToken", refreshToken);
ResponseUtil.responseMessage(response, InfoUtil.getInfo(UserError.TOKEN_IS_EXPIRED, jsonObject));
return false;
}
//将userId存到session
HttpSession session = request.getSession();
session.setAttribute("userId", userId);
return true;
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
三、 WebConfig配置
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
TokenInterceptor getTokenInterceptor() {
return new TokenInterceptor();
}
//注册拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册token设置
registry.addInterceptor(getTokenInterceptor())
.addPathPatterns("/**");
}
}
四、 使用方法
@TokenRequired //使用该注解表示该方法需要token
@PostMapping("/getUserInfo")
public Info getUserInfo() {
return userService.getUserInfo();
}
@Override
//登录
public Info login(Code code) {
Integer userId = userMapper.login(code);
//userId为null,说明用户名或密码错误
if (userId == null) {
return InfoUtil.getInfo(UserError.PASSWORD_OR_NAME_IS_ERROR);
}
//登录成功,返回token
JSONObject jsonObject = new JSONObject();
//根据userId生成token
String token = JwtUtil.sign(userId.toString());
//将token存于Redis
redisUtil.set("userToken_" + userId, token, 20, TimeUnit.DAYS);
jsonObject.put("token", token);
//返回token
return InfoUtil.getInfo(jsonObject);
}
Comments | 0 条评论