Commit 6c7282ff27cb0a611fae0d4e0ec5841244f367c4

Authored by preschooler
1 parent 56772d08

✨ feat(system): 添加令牌清理定时任务

yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/oauth2/OAuth2AccessTokenMapper.java
@@ -6,7 +6,9 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; @@ -6,7 +6,9 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; 6 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
7 import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.token.OAuth2AccessTokenPageReqVO; 7 import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.token.OAuth2AccessTokenPageReqVO;
8 import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; 8 import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
  9 +import org.apache.ibatis.annotations.Delete;
9 import org.apache.ibatis.annotations.Mapper; 10 import org.apache.ibatis.annotations.Mapper;
  11 +import org.apache.ibatis.annotations.Param;
10 12
11 import java.time.LocalDateTime; 13 import java.time.LocalDateTime;
12 import java.util.List; 14 import java.util.List;
@@ -37,4 +39,14 @@ public interface OAuth2AccessTokenMapper extends BaseMapperX<OAuth2AccessTokenDO @@ -37,4 +39,14 @@ public interface OAuth2AccessTokenMapper extends BaseMapperX<OAuth2AccessTokenDO
37 OAuth2AccessTokenDO::getUserType, userType); 39 OAuth2AccessTokenDO::getUserType, userType);
38 } 40 }
39 41
  42 + /**
  43 + * 物理删除指定过期时间之前的访问令牌
  44 + *
  45 + * @param expiresTime 最大时间
  46 + * @param limit 删除条数,防止一次删除太多
  47 + * @return 删除条数
  48 + */
  49 + @Delete("DELETE FROM system_oauth2_access_token WHERE expires_time < #{expiresTime} LIMIT #{limit}")
  50 + Integer deleteByExpiresTimeLt(@Param("expiresTime") LocalDateTime expiresTime, @Param("limit") Integer limit);
  51 +
40 } 52 }
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/oauth2/OAuth2RefreshTokenMapper.java
@@ -4,7 +4,11 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; @@ -4,7 +4,11 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
4 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
5 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; 5 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
6 import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2RefreshTokenDO; 6 import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2RefreshTokenDO;
  7 +import org.apache.ibatis.annotations.Delete;
7 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
  9 +import org.apache.ibatis.annotations.Param;
  10 +
  11 +import java.time.LocalDateTime;
8 12
9 @Mapper 13 @Mapper
10 public interface OAuth2RefreshTokenMapper extends BaseMapperX<OAuth2RefreshTokenDO> { 14 public interface OAuth2RefreshTokenMapper extends BaseMapperX<OAuth2RefreshTokenDO> {
@@ -19,4 +23,13 @@ public interface OAuth2RefreshTokenMapper extends BaseMapperX&lt;OAuth2RefreshToken @@ -19,4 +23,13 @@ public interface OAuth2RefreshTokenMapper extends BaseMapperX&lt;OAuth2RefreshToken
19 return selectOne(OAuth2RefreshTokenDO::getRefreshToken, refreshToken); 23 return selectOne(OAuth2RefreshTokenDO::getRefreshToken, refreshToken);
20 } 24 }
21 25
  26 + /**
  27 + * 物理删除指定过期时间之前的刷新令牌
  28 + *
  29 + * @param expiresTime 最大时间
  30 + * @param limit 删除条数,防止一次删除太多
  31 + * @return 删除条数
  32 + */
  33 + @Delete("DELETE FROM system_oauth2_refresh_token WHERE expires_time < #{expiresTime} LIMIT #{limit}")
  34 + Integer deleteByExpiresTimeLt(@Param("expiresTime") LocalDateTime expiresTime, @Param("limit") Integer limit);
22 } 35 }
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/job/token/TokenCleanJob.java 0 → 100644
  1 +package cn.iocoder.yudao.module.system.job.token;
  2 +
  3 +import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
  4 +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
  5 +import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
  6 +import jakarta.annotation.Resource;
  7 +import lombok.extern.slf4j.Slf4j;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +/**
  11 + * 物理删除过期 N 天的令牌的 Job
  12 + *
  13 + * @author preschooler
  14 + */
  15 +@Component
  16 +@Slf4j
  17 +public class TokenCleanJob implements JobHandler {
  18 +
  19 + @Resource
  20 + private OAuth2TokenService oauth2TokenService;
  21 +
  22 + /**
  23 + * 清理过期(14)天的令牌
  24 + */
  25 + private static final Integer JOB_CLEAN_RETAIN_DAY = 14;
  26 +
  27 + /**
  28 + * 每次删除间隔的条数,如果值太高可能会造成数据库的压力过大
  29 + */
  30 + private static final Integer DELETE_LIMIT = 100;
  31 +
  32 + @Override
  33 + @TenantIgnore
  34 + public String execute(String param) {
  35 + Integer refreshCount = oauth2TokenService.cleanRefreshToken(JOB_CLEAN_RETAIN_DAY, DELETE_LIMIT);
  36 + log.info("[execute][定时执行清理刷新令牌数量 ({}) 个]", refreshCount);
  37 + Integer accessCount = oauth2TokenService.cleanAccessToken(JOB_CLEAN_RETAIN_DAY, DELETE_LIMIT);
  38 + log.info("[execute][定时执行清理访问令牌数量 ({}) 个]", accessCount);
  39 + return String.format("定时执行清理刷新令牌数量 %s 个,访问令牌数量 %s 个", refreshCount, accessCount);
  40 + }
  41 +
  42 +}
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2TokenService.java
@@ -88,4 +88,19 @@ public interface OAuth2TokenService { @@ -88,4 +88,19 @@ public interface OAuth2TokenService {
88 */ 88 */
89 PageResult<OAuth2AccessTokenDO> getAccessTokenPage(OAuth2AccessTokenPageReqVO reqVO); 89 PageResult<OAuth2AccessTokenDO> getAccessTokenPage(OAuth2AccessTokenPageReqVO reqVO);
90 90
  91 + /**
  92 + * 清理过期 exceedDay 天的刷新令牌
  93 + *
  94 + * @param exceedDay 过期多少天就进行清理
  95 + * @param deleteLimit 清理的间隔条数
  96 + */
  97 + Integer cleanRefreshToken(Integer exceedDay, Integer deleteLimit);
  98 +
  99 + /**
  100 + * 清理过期 exceedDay 天的访问令牌
  101 + *
  102 + * @param exceedDay 过期多少天就进行清理
  103 + * @param deleteLimit 清理的间隔条数
  104 + */
  105 + Integer cleanAccessToken(Integer exceedDay, Integer deleteLimit);
91 } 106 }
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2TokenServiceImpl.java
@@ -243,4 +243,35 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService { @@ -243,4 +243,35 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
243 return IdUtil.fastSimpleUUID(); 243 return IdUtil.fastSimpleUUID();
244 } 244 }
245 245
  246 + @Override
  247 + public Integer cleanRefreshToken(Integer exceedDay, Integer deleteLimit) {
  248 + int count = 0;
  249 + LocalDateTime expireDate = LocalDateTime.now().minusDays(exceedDay);
  250 + // 循环删除,直到没有满足条件的数据
  251 + for (int i = 0; i < Short.MAX_VALUE; i++) {
  252 + int deleteCount = oauth2RefreshTokenMapper.deleteByExpiresTimeLt(expireDate, deleteLimit);
  253 + count += deleteCount;
  254 + // 达到删除预期条数,说明到底了
  255 + if (deleteCount < deleteLimit) {
  256 + break;
  257 + }
  258 + }
  259 + return count;
  260 + }
  261 +
  262 + @Override
  263 + public Integer cleanAccessToken(Integer exceedDay, Integer deleteLimit) {
  264 + int count = 0;
  265 + LocalDateTime expireDate = LocalDateTime.now().minusDays(exceedDay);
  266 + // 循环删除,直到没有满足条件的数据
  267 + for (int i = 0; i < Short.MAX_VALUE; i++) {
  268 + int deleteCount = oauth2AccessTokenMapper.deleteByExpiresTimeLt(expireDate, deleteLimit);
  269 + count += deleteCount;
  270 + // 达到删除预期条数,说明到底了
  271 + if (deleteCount < deleteLimit) {
  272 + break;
  273 + }
  274 + }
  275 + return count;
  276 + }
246 } 277 }