参考资料
SpringBoot教程(十四) | SpringBoot集成Redis(全网最全)
代码地址
https://github.com/laolang2016/jwt-study/tree/master/jwt-02
登录与注销
JWT 生成去掉过期时间
首先是 jwt
生成的时候不需要过期时间了
/**
* 生成 token
*/
public String buildToken(AuthUser authUser) {
authUser.setUuid(IdUtil.fastSimpleUUID());
Map<String, Object> claims = Maps.newHashMap();
// Date iat = new Date();
// Date exp = new Date(iat.getTime() + tokenProperties.getExpireTime() * 60 * 1000);
claims.put(GlobalConst.LOGIN_USER_KEY, authUser.getUuid());
claims.put("username", authUser.getUsername());
return Jwts.builder()
// .setIssuedAt(iat) // 签发时间
// .setExpiration(exp) // 过期时间
.setClaims(claims) // 自定义数据
.signWith(SignatureAlgorithm.HS512, tokenProperties.getSecret()).compact();
}
登录时把 Token 存入 Redis
/**
* 刷新 token
*
* @param authUser 用户信息, 将来可以携带一些其他信息, 比如角色信息
*/
private void refreshToken(AuthUser authUser) {
redisUtil.setCacheObject(getRedisKey(authUser.getUsername()), authUser, tokenProperties.getExpireTime(),
TimeUnit.MINUTES);
}
/**
* 获取 token redis key
*
* @param username 用户名
* @return 前缀
*/
private String getRedisKey(String username) {
return RedisPrefix.AUTH_TOKEN_PREFIX + username;
}
校验 Token 时判断 Redis 中 Token 是否存在
/**
* 校验 token
*/
public AuthUser verify(String token) {
try {
Claims claims = Jwts.parser().setSigningKey(tokenProperties.getSecret()).parseClaimsJws(token).getBody();
String username = claims.get("username", String.class);
AuthUser authUser = redisUtil.getCacheObject(getRedisKey(username));
if (Objects.isNull(authUser)) {
throw new AuthBusinessException(AuthBizCode.token_not_exist);
}
return authUser;
} catch (ExpiredJwtException e) {
throw new AuthBusinessException(AuthBizCode.login_expired);
} catch (Exception e) {
if (e instanceof AuthBusinessException) {
throw e;
}
throw new AuthBusinessException(AuthBizCode.error_token);
}
}
加一个退出接口
controller
/**
* 退出接口
*/
@GetMapping("logout")
public R<Void> logout() {
authLogic.logout();
return R.ok();
}
logic
public void logout() {
try {
String token = authUtil.getHeaderToken();
if (StrUtil.isBlank(token)) {
log.warn("token 不存在");
ServletKit.writeJson(response, JSONUtil.toJsonStr(R.doOverdue()));
return;
}
tokenService.removeToken(token);
} catch (Exception e) {
log.error("退出接口异常:{}", ExceptionUtils.getMessage(e));
throw new BusinessException(StatusCodeConst.ERROR);
}
}
tokenService
/**
* 删除 token
*
* @param token 请求头中的 token
*/
public void removeToken(String token) {
AuthUser authUser = verify(token);
redisUtil.del(getRedisKey(authUser.getUsername()));
}
在拦截器中已经调用了刷新 token 的方法