From 6187c1dd1a6e5dd0fe35c014f2feff10a56b5e38 Mon Sep 17 00:00:00 2001 From: zxy <497947426@qq.com> Date: Thu, 8 May 2025 15:32:01 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=BASaTokenListener=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=94=AF=E6=8C=81=EF=BC=8C=E6=94=AF=E6=8C=81=E4=BE=A6?= =?UTF-8?q?=E5=90=ACToken=E5=9C=A8=E9=BB=98=E8=AE=A4=E6=8C=81=E4=B9=85?= =?UTF-8?q?=E5=B1=82=E7=9A=84=E5=A4=B1=E6=95=88=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../satoken/dao/timedcache/SaTimedCache.java | 28 +++-- .../satoken/listener/SaTokenEventCenter.java | 103 ++++++++++-------- .../satoken/listener/SaTokenListener.java | 59 +++++----- .../listener/SaTokenListenerForLog.java | 26 +++-- .../listener/SaTokenListenerForSimple.java | 34 +++--- 5 files changed, 147 insertions(+), 103 deletions(-) diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/dao/timedcache/SaTimedCache.java b/sa-token-core/src/main/java/cn/dev33/satoken/dao/timedcache/SaTimedCache.java index 566f7baa..79e0ca74 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/dao/timedcache/SaTimedCache.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/dao/timedcache/SaTimedCache.java @@ -18,6 +18,8 @@ package cn.dev33.satoken.dao.timedcache; import cn.dev33.satoken.SaManager; import cn.dev33.satoken.dao.SaTokenDao; +import cn.dev33.satoken.listener.SaTokenEventCenter; +import cn.dev33.satoken.util.SaFoxUtil; import java.util.Set; @@ -44,7 +46,7 @@ public class SaTimedCache { this.expireMap = expireMap; } - + // ------------------------ 基础 API 读写操作 public Object getObject(String key) { @@ -100,6 +102,18 @@ public class SaTimedCache { if(expirationTime != null && expirationTime != SaTokenDao.NEVER_EXPIRE && expirationTime < System.currentTimeMillis()) { dataMap.remove(key); expireMap.remove(key); + + // 如果这个 key 是 token 才处理 + String tokenSegment = "token:"; + if (SaFoxUtil.isNotEmpty(key)) { + int index = key.indexOf(tokenSegment); + if (index != -1) { + // 截取 token 部分 + String token = key.substring(index + tokenSegment.length()); + // $$ 发布事件:token 失效 + SaTokenEventCenter.doTokenExpire(token); + } + } } } @@ -130,7 +144,7 @@ public class SaTimedCache { // 计算剩余时间并返回 (过期时间戳 - 当前时间戳) / 1000 转秒 long timeout = (expire - System.currentTimeMillis()) / 1000; - // 小于零时,视为不存在 + // 小于零时,视为不存在 if(timeout < 0) { dataMap.remove(key); expireMap.remove(key); @@ -140,12 +154,12 @@ public class SaTimedCache { } // --------- 定时清理过期数据 - + /** * 执行数据清理的线程引用 */ public Thread refreshThread; - + /** * 是否继续执行数据清理的线程标记 */ @@ -159,7 +173,7 @@ public class SaTimedCache { clearKeyByTimeout(s); } } - + /** * 初始化定时任务,定时清理过期数据 */ @@ -181,11 +195,11 @@ public class SaTimedCache { return; } // 执行清理 - refreshDataMap(); + refreshDataMap(); } catch (Exception e) { e.printStackTrace(); } - // 休眠N秒 + // 休眠N秒 int dataRefreshPeriod = SaManager.getConfig().getDataRefreshPeriod(); if(dataRefreshPeriod <= 0) { dataRefreshPeriod = 1; diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenEventCenter.java b/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenEventCenter.java index 68228dba..aa748aad 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenEventCenter.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenEventCenter.java @@ -29,24 +29,24 @@ import cn.dev33.satoken.stp.StpLogic; * Sa-Token 事件中心 事件发布器 * *

提供侦听器注册、事件发布能力

- * + * * @author click33 * @since 1.31.0 */ public class SaTokenEventCenter { - // --------- 注册侦听器 - + // --------- 注册侦听器 + private static List listenerList = new ArrayList<>(); - + static { - // 默认添加控制台日志侦听器 + // 默认添加控制台日志侦听器 listenerList.add(new SaTokenListenerForLog()); } /** * 获取已注册的所有侦听器 - * @return / + * @return / */ public static List getListenerList() { return listenerList; @@ -54,7 +54,7 @@ public class SaTokenEventCenter { /** * 重置侦听器集合 - * @param listenerList / + * @param listenerList / */ public static void setListenerList(List listenerList) { if(listenerList == null) { @@ -64,8 +64,8 @@ public class SaTokenEventCenter { } /** - * 注册一个侦听器 - * @param listener / + * 注册一个侦听器 + * @param listener / */ public static void registerListener(SaTokenListener listener) { if(listener == null) { @@ -75,8 +75,8 @@ public class SaTokenEventCenter { } /** - * 注册一组侦听器 - * @param listenerList / + * 注册一组侦听器 + * @param listenerList / */ public static void registerListenerList(List listenerList) { if(listenerList == null) { @@ -91,16 +91,16 @@ public class SaTokenEventCenter { } /** - * 移除一个侦听器 - * @param listener / + * 移除一个侦听器 + * @param listener / */ public static void removeListener(SaTokenListener listener) { listenerList.remove(listener); } /** - * 移除指定类型的所有侦听器 - * @param cls / + * 移除指定类型的所有侦听器 + * @param cls / */ public static void removeListener(Class cls) { ArrayList listenerListCopy = new ArrayList<>(listenerList); @@ -112,25 +112,25 @@ public class SaTokenEventCenter { } /** - * 清空所有已注册的侦听器 + * 清空所有已注册的侦听器 */ public static void clearListener() { listenerList.clear(); } /** - * 判断是否已经注册了指定侦听器 - * @param listener / - * @return / + * 判断是否已经注册了指定侦听器 + * @param listener / + * @return / */ public static boolean hasListener(SaTokenListener listener) { return listenerList.contains(listener); } /** - * 判断是否已经注册了指定类型的侦听器 - * @param cls / - * @return / + * 判断是否已经注册了指定类型的侦听器 + * @param cls / + * @return / */ public static boolean hasListener(Class cls) { for (SaTokenListener listener : listenerList) { @@ -140,15 +140,15 @@ public class SaTokenEventCenter { } return false; } - - - // --------- 事件发布 - + + + // --------- 事件发布 + /** * 事件发布:xx 账号登录 * @param loginType 账号类别 * @param loginId 账号id - * @param tokenValue 本次登录产生的 token 值 + * @param tokenValue 本次登录产生的 token 值 * @param loginParameter 登录参数 */ public static void doLogin(String loginType, Object loginId, String tokenValue, SaLoginParameter loginParameter) { @@ -156,7 +156,7 @@ public class SaTokenEventCenter { listener.doLogin(loginType, loginId, tokenValue, loginParameter); } } - + /** * 事件发布:xx 账号注销 * @param loginType 账号类别 @@ -168,12 +168,12 @@ public class SaTokenEventCenter { listener.doLogout(loginType, loginId, tokenValue); } } - + /** * 事件发布:xx 账号被踢下线 - * @param loginType 账号类别 - * @param loginId 账号id - * @param tokenValue token值 + * @param loginType 账号类别 + * @param loginId 账号id + * @param tokenValue token值 */ public static void doKickout(String loginType, Object loginId, String tokenValue) { for (SaTokenListener listener : listenerList) { @@ -197,8 +197,8 @@ public class SaTokenEventCenter { * 事件发布:xx 账号被封禁 * @param loginType 账号类别 * @param loginId 账号id - * @param service 指定服务 - * @param level 封禁等级 + * @param service 指定服务 + * @param level 封禁等级 * @param disableTime 封禁时长,单位: 秒 */ public static void doDisable(String loginType, Object loginId, String service, int level, long disableTime) { @@ -206,12 +206,12 @@ public class SaTokenEventCenter { listener.doDisable(loginType, loginId, service, level, disableTime); } } - + /** * 事件发布:xx 账号被解封 * @param loginType 账号类别 * @param loginId 账号id - * @param service 指定服务 + * @param service 指定服务 */ public static void doUntieDisable(String loginType, Object loginId, String service) { for (SaTokenListener listener : listenerList) { @@ -223,8 +223,8 @@ public class SaTokenEventCenter { * 事件发布:xx 账号完成二级认证 * @param loginType 账号类别 * @param tokenValue token值 - * @param service 指定服务 - * @param safeTime 认证时间,单位:秒 + * @param service 指定服务 + * @param safeTime 认证时间,单位:秒 */ public static void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) { for (SaTokenListener listener : listenerList) { @@ -235,7 +235,7 @@ public class SaTokenEventCenter { /** * 事件发布:xx 账号关闭二级认证 * @param loginType 账号类别 - * @param service 指定服务 + * @param service 指定服务 * @param tokenValue token值 */ public static void doCloseSafe(String loginType, String tokenValue, String service) { @@ -253,7 +253,7 @@ public class SaTokenEventCenter { listener.doCreateSession(id); } } - + /** * 事件发布:一个 SaSession 注销了 * @param id SessionId @@ -266,10 +266,10 @@ public class SaTokenEventCenter { /** * 事件发布:指定 Token 续期成功 - * - * @param tokenValue token 值 - * @param loginId 账号id - * @param timeout 续期时间 + * + * @param tokenValue token 值 + * @param loginId 账号id + * @param timeout 续期时间 */ public static void doRenewTimeout(String tokenValue, Object loginId, long timeout) { for (SaTokenListener listener : listenerList) { @@ -277,6 +277,17 @@ public class SaTokenEventCenter { } } + /** + * 事件发布:该 Token 失效(仅支持默认持久层) + * + * @param tokenValue token 值 + */ + public static void doTokenExpire(String tokenValue) { + for (SaTokenListener listener : listenerList) { + listener.doTokenExpire(tokenValue); + } + } + /** * 事件发布:有新的全局组件载入到框架中 * @param compName 组件名称 @@ -300,7 +311,7 @@ public class SaTokenEventCenter { /** * 事件发布:有新的 StpLogic 载入到框架中 - * @param stpLogic / + * @param stpLogic / */ public static void doSetStpLogic(StpLogic stpLogic) { for (SaTokenListener listener : listenerList) { @@ -310,7 +321,7 @@ public class SaTokenEventCenter { /** * 事件发布:有新的全局配置载入到框架中 - * @param config / + * @param config / */ public static void doSetConfig(SaTokenConfig config) { for (SaTokenListener listener : listenerList) { diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListener.java b/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListener.java index ed0ca42a..80a37954 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListener.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListener.java @@ -31,27 +31,27 @@ import cn.dev33.satoken.stp.StpLogic; public interface SaTokenListener { /** - * 每次登录时触发 + * 每次登录时触发 * @param loginType 账号类别 * @param loginId 账号id - * @param tokenValue 本次登录产生的 token 值 + * @param tokenValue 本次登录产生的 token 值 * @param loginParameter 登录参数 */ void doLogin(String loginType, Object loginId, String tokenValue, SaLoginParameter loginParameter); - + /** - * 每次注销时触发 + * 每次注销时触发 * @param loginType 账号类别 * @param loginId 账号id * @param tokenValue token值 */ void doLogout(String loginType, Object loginId, String tokenValue); - + /** - * 每次被踢下线时触发 - * @param loginType 账号类别 - * @param loginId 账号id - * @param tokenValue token值 + * 每次被踢下线时触发 + * @param loginType 账号类别 + * @param loginId 账号id + * @param tokenValue token值 */ void doKickout(String loginType, Object loginId, String tokenValue); @@ -67,17 +67,17 @@ public interface SaTokenListener { * 每次被封禁时触发 * @param loginType 账号类别 * @param loginId 账号id - * @param service 指定服务 - * @param level 封禁等级 + * @param service 指定服务 + * @param level 封禁等级 * @param disableTime 封禁时长,单位: 秒 */ void doDisable(String loginType, Object loginId, String service, int level, long disableTime); - + /** * 每次被解封时触发 * @param loginType 账号类别 * @param loginId 账号id - * @param service 指定服务 + * @param service 指定服务 */ void doUntieDisable(String loginType, Object loginId, String service); @@ -85,8 +85,8 @@ public interface SaTokenListener { * 每次打开二级认证时触发 * @param loginType 账号类别 * @param tokenValue token值 - * @param service 指定服务 - * @param safeTime 认证时间,单位:秒 + * @param service 指定服务 + * @param safeTime 认证时间,单位:秒 */ void doOpenSafe(String loginType, String tokenValue, String service, long safeTime); @@ -94,7 +94,7 @@ public interface SaTokenListener { * 每次关闭二级认证时触发 * @param loginType 账号类别 * @param tokenValue token值 - * @param service 指定服务 + * @param service 指定服务 */ void doCloseSafe(String loginType, String tokenValue, String service); @@ -103,7 +103,7 @@ public interface SaTokenListener { * @param id SessionId */ void doCreateSession(String id); - + /** * 每次注销 SaSession 时触发 * @param id SessionId @@ -112,15 +112,22 @@ public interface SaTokenListener { /** * 每次 Token 续期时触发(注意:是 timeout 续期,而不是 active-timeout 续期) - * - * @param tokenValue token 值 - * @param loginId 账号id - * @param timeout 续期时间 + * + * @param tokenValue token 值 + * @param loginId 账号id + * @param timeout 续期时间 */ void doRenewTimeout(String tokenValue, Object loginId, long timeout); /** - * 全局组件载入 + * 每次 Token 失效时触发(仅支持默认持久层) + * + * @param tokenValue token 值 + */ + void doTokenExpire(String tokenValue); + + /** + * 全局组件载入 * @param compName 组件名称 * @param compObj 组件对象 */ @@ -133,14 +140,14 @@ public interface SaTokenListener { default void doRegisterAnnotationHandler(SaAnnotationHandlerInterface handler) {} /** - * StpLogic 对象替换 - * @param stpLogic / + * StpLogic 对象替换 + * @param stpLogic / */ default void doSetStpLogic(StpLogic stpLogic) {} /** - * 载入全局配置 - * @param config / + * 载入全局配置 + * @param config / */ default void doSetConfig(SaTokenConfig config) {} diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListenerForLog.java b/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListenerForLog.java index cb770e83..74d4738d 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListenerForLog.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListenerForLog.java @@ -25,14 +25,14 @@ import static cn.dev33.satoken.SaManager.log; /** * Sa-Token 侦听器的一个实现:Log 打印 - * + * * @author click33 * @since 1.33.0 */ public class SaTokenListenerForLog implements SaTokenListener { /** - * 每次登录时触发 + * 每次登录时触发 */ @Override public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginParameter loginParameter) { @@ -40,7 +40,7 @@ public class SaTokenListenerForLog implements SaTokenListener { } /** - * 每次注销时触发 + * 每次注销时触发 */ @Override public void doLogout(String loginType, Object loginId, String tokenValue) { @@ -78,7 +78,7 @@ public class SaTokenListenerForLog implements SaTokenListener { public void doUntieDisable(String loginType, Object loginId, String service) { log.info("账号 {} [{}服务] 解封成功 (loginType={})", loginId, service, loginType); } - + /** * 每次打开二级认证时触发 */ @@ -119,9 +119,17 @@ public class SaTokenListenerForLog implements SaTokenListener { log.info("token 续期成功, {} 秒后到期, 帐号={}, token值={} ", timeout, loginId, tokenValue); } + /** + * 每次 Token 失效时触发(仅支持默认持久层) + */ + @Override + public void doTokenExpire(String tokenValue) { + log.info("token 失效, token值={} ", tokenValue); + } + /** - * 全局组件载入 + * 全局组件载入 * @param compName 组件名称 * @param compObj 组件对象 */ @@ -143,8 +151,8 @@ public class SaTokenListenerForLog implements SaTokenListener { } /** - * StpLogic 对象替换 - * @param stpLogic / + * StpLogic 对象替换 + * @param stpLogic / */ @Override public void doSetStpLogic(StpLogic stpLogic) { @@ -154,8 +162,8 @@ public class SaTokenListenerForLog implements SaTokenListener { } /** - * 载入全局配置 - * @param config / + * 载入全局配置 + * @param config / */ @Override public void doSetConfig(SaTokenConfig config) { diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListenerForSimple.java b/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListenerForSimple.java index f7e30f5c..564115b4 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListenerForSimple.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/listener/SaTokenListenerForSimple.java @@ -18,10 +18,10 @@ package cn.dev33.satoken.listener; import cn.dev33.satoken.stp.parameter.SaLoginParameter; /** - * Sa-Token 侦听器,默认空实现 - * + * Sa-Token 侦听器,默认空实现 + * *

对所有事件方法提供空实现,方便开发者通过继承此类快速实现一个可用的侦听器

- * + * * @author click33 * @since 1.31.0 */ @@ -29,52 +29,52 @@ public class SaTokenListenerForSimple implements SaTokenListener { @Override public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginParameter loginParameter) { - + } @Override public void doLogout(String loginType, Object loginId, String tokenValue) { - + } @Override public void doKickout(String loginType, Object loginId, String tokenValue) { - + } @Override public void doReplaced(String loginType, Object loginId, String tokenValue) { - + } @Override public void doDisable(String loginType, Object loginId, String service, int level, long disableTime) { - + } @Override public void doUntieDisable(String loginType, Object loginId, String service) { - + } - + @Override public void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) { - + } @Override public void doCloseSafe(String loginType, String tokenValue, String service) { - + } @Override public void doCreateSession(String id) { - + } @Override public void doLogoutSession(String id) { - + } @Override @@ -82,5 +82,9 @@ public class SaTokenListenerForSimple implements SaTokenListener { } - + @Override + public void doTokenExpire(String tokenValue) { + } + + }