package com.ruoyi.errand.utils;
|
|
|
|
import io.jsonwebtoken.Claims;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.stereotype.Service;
|
|
import java.util.Date;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
@Service
|
@Slf4j
|
public class TokenBlacklistService {
|
private final RedisTemplate redisTemplate;
|
|
// 使用构造器注入替代字段注入
|
@Autowired
|
public TokenBlacklistService(RedisTemplate redisTemplate) {
|
this.redisTemplate = redisTemplate;
|
}
|
|
// 黑名单键前缀
|
private static final String BLACKLIST_KEY_PREFIX = "token:blacklist:";
|
|
// 过期时间缓冲(防止刚好过期时还在黑名单中)
|
private static final long EXPIRATION_BUFFER_MS = 30000; // 30秒
|
|
/**
|
* 添加Token到黑名单
|
* @param token JWT Token
|
*/
|
public void addToBlacklist(String token) {
|
try {
|
String realToken=token.substring(4);
|
Claims claims = JwtUtil.parseJWT(realToken);
|
Date expiration = claims.getExpiration();
|
long ttl = expiration.getTime() - System.currentTimeMillis() + EXPIRATION_BUFFER_MS;
|
|
if (ttl > 0) {
|
redisTemplate.opsForValue().set(
|
BLACKLIST_KEY_PREFIX + realToken,
|
"1",
|
ttl,
|
TimeUnit.MILLISECONDS
|
);
|
log.info("Token已加入黑名单,剩余有效期: {} 毫秒", ttl);
|
}
|
} catch (Exception e) {
|
log.error("添加Token到黑名单失败", e);
|
}
|
}
|
|
/**
|
* 检查Token是否在黑名单中
|
* @param token JWT Token
|
* @return true-在黑名单中,false-不在黑名单中
|
*/
|
public boolean isBlacklisted(String token) {
|
Boolean exists = redisTemplate.hasKey(BLACKLIST_KEY_PREFIX + token);
|
return exists != null && exists;
|
}
|
|
/**
|
* 清理过期Token(Redis会自动过期,此方法可选保留)
|
*/
|
@Scheduled(fixedRate = 2, timeUnit = TimeUnit.HOURS)
|
public void cleanupExpiredTokens() {
|
log.info("Token黑名单清理任务开始执行");
|
// Redis有自动过期机制,此方法主要做日志记录
|
log.info("Token黑名单清理任务完成(Redis自动处理过期)");
|
}
|
|
/**
|
* 检查JWT Token是否过期
|
* @param token JWT Token字符串
|
* @return true-已过期,false-未过期
|
*/
|
public boolean isTokenExpired(String token) {
|
try {
|
Claims claims = JwtUtil.parseJWT(token);
|
return claims.getExpiration().before(new Date());
|
} catch (Exception e) {
|
// 如果解析过程中出现异常(如Token无效、已过期等),视为已过期
|
return true;
|
}
|
}
|
}
|