fix: 修改刷新token逻辑

This commit is contained in:
2026-06-17 09:23:11 +08:00
parent b9ed1cd326
commit 39d4c018e4
3 changed files with 21 additions and 387 deletions

View File

@@ -47,6 +47,9 @@ public class RefreshTokenServiceImpl implements RefreshTokenService {
@Override
public String create(String userId) {
if (userId == null || userId.isBlank()) {
throw new BusinessException(ErrorCode.BAD_REQUEST, "用户ID不能为空");
}
// 先清除该用户之前的 refresh token确保一个用户只有一个有效 token
String oldToken = get(USER_KEY_PREFIX + userId);
if (oldToken != null) {
@@ -78,21 +81,30 @@ public class RefreshTokenServiceImpl implements RefreshTokenService {
@Override
public String rotate(String oldToken) {
String userId = validate(oldToken);
delete(KEY_PREFIX + oldToken);
// 先删反向映射,再删正向映射:
// 若反向映射删除失败,正向映射仍存在,调用方可重试;
// 若反向已删除而正向删除失败,正向映射仍存在,重试仍可通过。
delete(USER_KEY_PREFIX + userId);
delete(KEY_PREFIX + oldToken);
log.debug("旧刷新令牌已删除: userId={}", userId);
return create(userId);
}
@Override
public void revoke(String token) {
if (token != null && !token.isBlank()) {
if (token == null || token.isBlank()) {
return;
}
try {
String userId = get(KEY_PREFIX + token);
if (userId != null) {
delete(USER_KEY_PREFIX + userId);
}
delete(KEY_PREFIX + token);
log.debug("刷新令牌已撤销");
} catch (BusinessException e) {
// 登出时 Redis 不可用,记录日志后放行,不影响用户登出
log.warn("撤销刷新令牌失败Redis 不可用),跳过清理: token={}", token, e);
}
}
@@ -110,6 +122,9 @@ public class RefreshTokenServiceImpl implements RefreshTokenService {
/**
* 从 Redis 读取字符串(读取时续期)
*
* @return 值key 不存在时返回 null
* @throws BusinessException Redis 操作失败时抛出
*/
private String get(String key) {
try {
@@ -120,18 +135,21 @@ public class RefreshTokenServiceImpl implements RefreshTokenService {
return value;
} catch (Exception e) {
log.error("查询缓存失败: key={}", key, e);
return null;
throw new BusinessException(ErrorCode.INTERNAL_ERROR, "刷新令牌操作失败");
}
}
/**
* 从 Redis 删除 key
*
* @throws BusinessException Redis 操作失败时抛出
*/
private void delete(String key) {
try {
stringRedisTemplate.delete(key);
} catch (Exception e) {
log.error("删除缓存失败: key={}", key, e);
throw new BusinessException(ErrorCode.INTERNAL_ERROR, "刷新令牌操作失败");
}
}