feat: 为SaTokenListener添加支持,支持侦听Token在默认持久层的失效事件

This commit is contained in:
zxy 2025-05-08 15:32:01 +08:00
parent 2ecd52b3be
commit 6187c1dd1a
5 changed files with 147 additions and 103 deletions

View File

@ -18,6 +18,8 @@ package cn.dev33.satoken.dao.timedcache;
import cn.dev33.satoken.SaManager; import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.dao.SaTokenDao; import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.listener.SaTokenEventCenter;
import cn.dev33.satoken.util.SaFoxUtil;
import java.util.Set; import java.util.Set;
@ -44,7 +46,7 @@ public class SaTimedCache {
this.expireMap = expireMap; this.expireMap = expireMap;
} }
// ------------------------ 基础 API 读写操作 // ------------------------ 基础 API 读写操作
public Object getObject(String key) { public Object getObject(String key) {
@ -100,6 +102,18 @@ public class SaTimedCache {
if(expirationTime != null && expirationTime != SaTokenDao.NEVER_EXPIRE && expirationTime < System.currentTimeMillis()) { if(expirationTime != null && expirationTime != SaTokenDao.NEVER_EXPIRE && expirationTime < System.currentTimeMillis()) {
dataMap.remove(key); dataMap.remove(key);
expireMap.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 转秒 // 计算剩余时间并返回 过期时间戳 - 当前时间戳 / 1000 转秒
long timeout = (expire - System.currentTimeMillis()) / 1000; long timeout = (expire - System.currentTimeMillis()) / 1000;
// 小于零时视为不存在 // 小于零时视为不存在
if(timeout < 0) { if(timeout < 0) {
dataMap.remove(key); dataMap.remove(key);
expireMap.remove(key); expireMap.remove(key);
@ -140,12 +154,12 @@ public class SaTimedCache {
} }
// --------- 定时清理过期数据 // --------- 定时清理过期数据
/** /**
* 执行数据清理的线程引用 * 执行数据清理的线程引用
*/ */
public Thread refreshThread; public Thread refreshThread;
/** /**
* 是否继续执行数据清理的线程标记 * 是否继续执行数据清理的线程标记
*/ */
@ -159,7 +173,7 @@ public class SaTimedCache {
clearKeyByTimeout(s); clearKeyByTimeout(s);
} }
} }
/** /**
* 初始化定时任务定时清理过期数据 * 初始化定时任务定时清理过期数据
*/ */
@ -181,11 +195,11 @@ public class SaTimedCache {
return; return;
} }
// 执行清理 // 执行清理
refreshDataMap(); refreshDataMap();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
// 休眠N秒 // 休眠N秒
int dataRefreshPeriod = SaManager.getConfig().getDataRefreshPeriod(); int dataRefreshPeriod = SaManager.getConfig().getDataRefreshPeriod();
if(dataRefreshPeriod <= 0) { if(dataRefreshPeriod <= 0) {
dataRefreshPeriod = 1; dataRefreshPeriod = 1;

View File

@ -29,24 +29,24 @@ import cn.dev33.satoken.stp.StpLogic;
* Sa-Token 事件中心 事件发布器 * Sa-Token 事件中心 事件发布器
* *
* <p> 提供侦听器注册事件发布能力 </p> * <p> 提供侦听器注册事件发布能力 </p>
* *
* @author click33 * @author click33
* @since 1.31.0 * @since 1.31.0
*/ */
public class SaTokenEventCenter { public class SaTokenEventCenter {
// --------- 注册侦听器 // --------- 注册侦听器
private static List<SaTokenListener> listenerList = new ArrayList<>(); private static List<SaTokenListener> listenerList = new ArrayList<>();
static { static {
// 默认添加控制台日志侦听器 // 默认添加控制台日志侦听器
listenerList.add(new SaTokenListenerForLog()); listenerList.add(new SaTokenListenerForLog());
} }
/** /**
* 获取已注册的所有侦听器 * 获取已注册的所有侦听器
* @return / * @return /
*/ */
public static List<SaTokenListener> getListenerList() { public static List<SaTokenListener> getListenerList() {
return listenerList; return listenerList;
@ -54,7 +54,7 @@ public class SaTokenEventCenter {
/** /**
* 重置侦听器集合 * 重置侦听器集合
* @param listenerList / * @param listenerList /
*/ */
public static void setListenerList(List<SaTokenListener> listenerList) { public static void setListenerList(List<SaTokenListener> listenerList) {
if(listenerList == null) { if(listenerList == null) {
@ -64,8 +64,8 @@ public class SaTokenEventCenter {
} }
/** /**
* 注册一个侦听器 * 注册一个侦听器
* @param listener / * @param listener /
*/ */
public static void registerListener(SaTokenListener listener) { public static void registerListener(SaTokenListener listener) {
if(listener == null) { if(listener == null) {
@ -75,8 +75,8 @@ public class SaTokenEventCenter {
} }
/** /**
* 注册一组侦听器 * 注册一组侦听器
* @param listenerList / * @param listenerList /
*/ */
public static void registerListenerList(List<SaTokenListener> listenerList) { public static void registerListenerList(List<SaTokenListener> listenerList) {
if(listenerList == null) { if(listenerList == null) {
@ -91,16 +91,16 @@ public class SaTokenEventCenter {
} }
/** /**
* 移除一个侦听器 * 移除一个侦听器
* @param listener / * @param listener /
*/ */
public static void removeListener(SaTokenListener listener) { public static void removeListener(SaTokenListener listener) {
listenerList.remove(listener); listenerList.remove(listener);
} }
/** /**
* 移除指定类型的所有侦听器 * 移除指定类型的所有侦听器
* @param cls / * @param cls /
*/ */
public static void removeListener(Class<? extends SaTokenListener> cls) { public static void removeListener(Class<? extends SaTokenListener> cls) {
ArrayList<SaTokenListener> listenerListCopy = new ArrayList<>(listenerList); ArrayList<SaTokenListener> listenerListCopy = new ArrayList<>(listenerList);
@ -112,25 +112,25 @@ public class SaTokenEventCenter {
} }
/** /**
* 清空所有已注册的侦听器 * 清空所有已注册的侦听器
*/ */
public static void clearListener() { public static void clearListener() {
listenerList.clear(); listenerList.clear();
} }
/** /**
* 判断是否已经注册了指定侦听器 * 判断是否已经注册了指定侦听器
* @param listener / * @param listener /
* @return / * @return /
*/ */
public static boolean hasListener(SaTokenListener listener) { public static boolean hasListener(SaTokenListener listener) {
return listenerList.contains(listener); return listenerList.contains(listener);
} }
/** /**
* 判断是否已经注册了指定类型的侦听器 * 判断是否已经注册了指定类型的侦听器
* @param cls / * @param cls /
* @return / * @return /
*/ */
public static boolean hasListener(Class<? extends SaTokenListener> cls) { public static boolean hasListener(Class<? extends SaTokenListener> cls) {
for (SaTokenListener listener : listenerList) { for (SaTokenListener listener : listenerList) {
@ -140,15 +140,15 @@ public class SaTokenEventCenter {
} }
return false; return false;
} }
// --------- 事件发布 // --------- 事件发布
/** /**
* 事件发布xx 账号登录 * 事件发布xx 账号登录
* @param loginType 账号类别 * @param loginType 账号类别
* @param loginId 账号id * @param loginId 账号id
* @param tokenValue 本次登录产生的 token * @param tokenValue 本次登录产生的 token
* @param loginParameter 登录参数 * @param loginParameter 登录参数
*/ */
public static void doLogin(String loginType, Object loginId, String tokenValue, SaLoginParameter 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); listener.doLogin(loginType, loginId, tokenValue, loginParameter);
} }
} }
/** /**
* 事件发布xx 账号注销 * 事件发布xx 账号注销
* @param loginType 账号类别 * @param loginType 账号类别
@ -168,12 +168,12 @@ public class SaTokenEventCenter {
listener.doLogout(loginType, loginId, tokenValue); listener.doLogout(loginType, loginId, tokenValue);
} }
} }
/** /**
* 事件发布xx 账号被踢下线 * 事件发布xx 账号被踢下线
* @param loginType 账号类别 * @param loginType 账号类别
* @param loginId 账号id * @param loginId 账号id
* @param tokenValue token值 * @param tokenValue token值
*/ */
public static void doKickout(String loginType, Object loginId, String tokenValue) { public static void doKickout(String loginType, Object loginId, String tokenValue) {
for (SaTokenListener listener : listenerList) { for (SaTokenListener listener : listenerList) {
@ -197,8 +197,8 @@ public class SaTokenEventCenter {
* 事件发布xx 账号被封禁 * 事件发布xx 账号被封禁
* @param loginType 账号类别 * @param loginType 账号类别
* @param loginId 账号id * @param loginId 账号id
* @param service 指定服务 * @param service 指定服务
* @param level 封禁等级 * @param level 封禁等级
* @param disableTime 封禁时长单位: * @param disableTime 封禁时长单位:
*/ */
public static void doDisable(String loginType, Object loginId, String service, int level, long 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); listener.doDisable(loginType, loginId, service, level, disableTime);
} }
} }
/** /**
* 事件发布xx 账号被解封 * 事件发布xx 账号被解封
* @param loginType 账号类别 * @param loginType 账号类别
* @param loginId 账号id * @param loginId 账号id
* @param service 指定服务 * @param service 指定服务
*/ */
public static void doUntieDisable(String loginType, Object loginId, String service) { public static void doUntieDisable(String loginType, Object loginId, String service) {
for (SaTokenListener listener : listenerList) { for (SaTokenListener listener : listenerList) {
@ -223,8 +223,8 @@ public class SaTokenEventCenter {
* 事件发布xx 账号完成二级认证 * 事件发布xx 账号完成二级认证
* @param loginType 账号类别 * @param loginType 账号类别
* @param tokenValue token值 * @param tokenValue token值
* @param service 指定服务 * @param service 指定服务
* @param safeTime 认证时间单位 * @param safeTime 认证时间单位
*/ */
public static void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) { public static void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) {
for (SaTokenListener listener : listenerList) { for (SaTokenListener listener : listenerList) {
@ -235,7 +235,7 @@ public class SaTokenEventCenter {
/** /**
* 事件发布xx 账号关闭二级认证 * 事件发布xx 账号关闭二级认证
* @param loginType 账号类别 * @param loginType 账号类别
* @param service 指定服务 * @param service 指定服务
* @param tokenValue token值 * @param tokenValue token值
*/ */
public static void doCloseSafe(String loginType, String tokenValue, String service) { public static void doCloseSafe(String loginType, String tokenValue, String service) {
@ -253,7 +253,7 @@ public class SaTokenEventCenter {
listener.doCreateSession(id); listener.doCreateSession(id);
} }
} }
/** /**
* 事件发布一个 SaSession 注销了 * 事件发布一个 SaSession 注销了
* @param id SessionId * @param id SessionId
@ -266,10 +266,10 @@ public class SaTokenEventCenter {
/** /**
* 事件发布指定 Token 续期成功 * 事件发布指定 Token 续期成功
* *
* @param tokenValue token * @param tokenValue token
* @param loginId 账号id * @param loginId 账号id
* @param timeout 续期时间 * @param timeout 续期时间
*/ */
public static void doRenewTimeout(String tokenValue, Object loginId, long timeout) { public static void doRenewTimeout(String tokenValue, Object loginId, long timeout) {
for (SaTokenListener listener : listenerList) { 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 组件名称 * @param compName 组件名称
@ -300,7 +311,7 @@ public class SaTokenEventCenter {
/** /**
* 事件发布有新的 StpLogic 载入到框架中 * 事件发布有新的 StpLogic 载入到框架中
* @param stpLogic / * @param stpLogic /
*/ */
public static void doSetStpLogic(StpLogic stpLogic) { public static void doSetStpLogic(StpLogic stpLogic) {
for (SaTokenListener listener : listenerList) { for (SaTokenListener listener : listenerList) {
@ -310,7 +321,7 @@ public class SaTokenEventCenter {
/** /**
* 事件发布有新的全局配置载入到框架中 * 事件发布有新的全局配置载入到框架中
* @param config / * @param config /
*/ */
public static void doSetConfig(SaTokenConfig config) { public static void doSetConfig(SaTokenConfig config) {
for (SaTokenListener listener : listenerList) { for (SaTokenListener listener : listenerList) {

View File

@ -31,27 +31,27 @@ import cn.dev33.satoken.stp.StpLogic;
public interface SaTokenListener { public interface SaTokenListener {
/** /**
* 每次登录时触发 * 每次登录时触发
* @param loginType 账号类别 * @param loginType 账号类别
* @param loginId 账号id * @param loginId 账号id
* @param tokenValue 本次登录产生的 token * @param tokenValue 本次登录产生的 token
* @param loginParameter 登录参数 * @param loginParameter 登录参数
*/ */
void doLogin(String loginType, Object loginId, String tokenValue, SaLoginParameter loginParameter); void doLogin(String loginType, Object loginId, String tokenValue, SaLoginParameter loginParameter);
/** /**
* 每次注销时触发 * 每次注销时触发
* @param loginType 账号类别 * @param loginType 账号类别
* @param loginId 账号id * @param loginId 账号id
* @param tokenValue token值 * @param tokenValue token值
*/ */
void doLogout(String loginType, Object loginId, String tokenValue); void doLogout(String loginType, Object loginId, String tokenValue);
/** /**
* 每次被踢下线时触发 * 每次被踢下线时触发
* @param loginType 账号类别 * @param loginType 账号类别
* @param loginId 账号id * @param loginId 账号id
* @param tokenValue token值 * @param tokenValue token值
*/ */
void doKickout(String loginType, Object loginId, String tokenValue); void doKickout(String loginType, Object loginId, String tokenValue);
@ -67,17 +67,17 @@ public interface SaTokenListener {
* 每次被封禁时触发 * 每次被封禁时触发
* @param loginType 账号类别 * @param loginType 账号类别
* @param loginId 账号id * @param loginId 账号id
* @param service 指定服务 * @param service 指定服务
* @param level 封禁等级 * @param level 封禁等级
* @param disableTime 封禁时长单位: * @param disableTime 封禁时长单位:
*/ */
void doDisable(String loginType, Object loginId, String service, int level, long disableTime); void doDisable(String loginType, Object loginId, String service, int level, long disableTime);
/** /**
* 每次被解封时触发 * 每次被解封时触发
* @param loginType 账号类别 * @param loginType 账号类别
* @param loginId 账号id * @param loginId 账号id
* @param service 指定服务 * @param service 指定服务
*/ */
void doUntieDisable(String loginType, Object loginId, String service); void doUntieDisable(String loginType, Object loginId, String service);
@ -85,8 +85,8 @@ public interface SaTokenListener {
* 每次打开二级认证时触发 * 每次打开二级认证时触发
* @param loginType 账号类别 * @param loginType 账号类别
* @param tokenValue token值 * @param tokenValue token值
* @param service 指定服务 * @param service 指定服务
* @param safeTime 认证时间单位 * @param safeTime 认证时间单位
*/ */
void doOpenSafe(String loginType, String tokenValue, String service, long safeTime); void doOpenSafe(String loginType, String tokenValue, String service, long safeTime);
@ -94,7 +94,7 @@ public interface SaTokenListener {
* 每次关闭二级认证时触发 * 每次关闭二级认证时触发
* @param loginType 账号类别 * @param loginType 账号类别
* @param tokenValue token值 * @param tokenValue token值
* @param service 指定服务 * @param service 指定服务
*/ */
void doCloseSafe(String loginType, String tokenValue, String service); void doCloseSafe(String loginType, String tokenValue, String service);
@ -103,7 +103,7 @@ public interface SaTokenListener {
* @param id SessionId * @param id SessionId
*/ */
void doCreateSession(String id); void doCreateSession(String id);
/** /**
* 每次注销 SaSession 时触发 * 每次注销 SaSession 时触发
* @param id SessionId * @param id SessionId
@ -112,15 +112,22 @@ public interface SaTokenListener {
/** /**
* 每次 Token 续期时触发注意 timeout 续期而不是 active-timeout 续期 * 每次 Token 续期时触发注意 timeout 续期而不是 active-timeout 续期
* *
* @param tokenValue token * @param tokenValue token
* @param loginId 账号id * @param loginId 账号id
* @param timeout 续期时间 * @param timeout 续期时间
*/ */
void doRenewTimeout(String tokenValue, Object loginId, long timeout); void doRenewTimeout(String tokenValue, Object loginId, long timeout);
/** /**
* 全局组件载入 * 每次 Token 失效时触发仅支持默认持久层
*
* @param tokenValue token
*/
void doTokenExpire(String tokenValue);
/**
* 全局组件载入
* @param compName 组件名称 * @param compName 组件名称
* @param compObj 组件对象 * @param compObj 组件对象
*/ */
@ -133,14 +140,14 @@ public interface SaTokenListener {
default void doRegisterAnnotationHandler(SaAnnotationHandlerInterface<?> handler) {} default void doRegisterAnnotationHandler(SaAnnotationHandlerInterface<?> handler) {}
/** /**
* StpLogic 对象替换 * StpLogic 对象替换
* @param stpLogic / * @param stpLogic /
*/ */
default void doSetStpLogic(StpLogic stpLogic) {} default void doSetStpLogic(StpLogic stpLogic) {}
/** /**
* 载入全局配置 * 载入全局配置
* @param config / * @param config /
*/ */
default void doSetConfig(SaTokenConfig config) {} default void doSetConfig(SaTokenConfig config) {}

View File

@ -25,14 +25,14 @@ import static cn.dev33.satoken.SaManager.log;
/** /**
* Sa-Token 侦听器的一个实现Log 打印 * Sa-Token 侦听器的一个实现Log 打印
* *
* @author click33 * @author click33
* @since 1.33.0 * @since 1.33.0
*/ */
public class SaTokenListenerForLog implements SaTokenListener { public class SaTokenListenerForLog implements SaTokenListener {
/** /**
* 每次登录时触发 * 每次登录时触发
*/ */
@Override @Override
public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginParameter loginParameter) { public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginParameter loginParameter) {
@ -40,7 +40,7 @@ public class SaTokenListenerForLog implements SaTokenListener {
} }
/** /**
* 每次注销时触发 * 每次注销时触发
*/ */
@Override @Override
public void doLogout(String loginType, Object loginId, String tokenValue) { 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) { public void doUntieDisable(String loginType, Object loginId, String service) {
log.info("账号 {} [{}服务] 解封成功 (loginType={})", loginId, service, loginType); log.info("账号 {} [{}服务] 解封成功 (loginType={})", loginId, service, loginType);
} }
/** /**
* 每次打开二级认证时触发 * 每次打开二级认证时触发
*/ */
@ -119,9 +119,17 @@ public class SaTokenListenerForLog implements SaTokenListener {
log.info("token 续期成功, {} 秒后到期, 帐号={}, token值={} ", timeout, loginId, tokenValue); log.info("token 续期成功, {} 秒后到期, 帐号={}, token值={} ", timeout, loginId, tokenValue);
} }
/**
* 每次 Token 失效时触发仅支持默认持久层
*/
@Override
public void doTokenExpire(String tokenValue) {
log.info("token 失效, token值={} ", tokenValue);
}
/** /**
* 全局组件载入 * 全局组件载入
* @param compName 组件名称 * @param compName 组件名称
* @param compObj 组件对象 * @param compObj 组件对象
*/ */
@ -143,8 +151,8 @@ public class SaTokenListenerForLog implements SaTokenListener {
} }
/** /**
* StpLogic 对象替换 * StpLogic 对象替换
* @param stpLogic / * @param stpLogic /
*/ */
@Override @Override
public void doSetStpLogic(StpLogic stpLogic) { public void doSetStpLogic(StpLogic stpLogic) {
@ -154,8 +162,8 @@ public class SaTokenListenerForLog implements SaTokenListener {
} }
/** /**
* 载入全局配置 * 载入全局配置
* @param config / * @param config /
*/ */
@Override @Override
public void doSetConfig(SaTokenConfig config) { public void doSetConfig(SaTokenConfig config) {

View File

@ -18,10 +18,10 @@ package cn.dev33.satoken.listener;
import cn.dev33.satoken.stp.parameter.SaLoginParameter; import cn.dev33.satoken.stp.parameter.SaLoginParameter;
/** /**
* Sa-Token 侦听器默认空实现 * Sa-Token 侦听器默认空实现
* *
* <p> 对所有事件方法提供空实现方便开发者通过继承此类快速实现一个可用的侦听器 </p> * <p> 对所有事件方法提供空实现方便开发者通过继承此类快速实现一个可用的侦听器 </p>
* *
* @author click33 * @author click33
* @since 1.31.0 * @since 1.31.0
*/ */
@ -29,52 +29,52 @@ public class SaTokenListenerForSimple implements SaTokenListener {
@Override @Override
public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginParameter loginParameter) { public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginParameter loginParameter) {
} }
@Override @Override
public void doLogout(String loginType, Object loginId, String tokenValue) { public void doLogout(String loginType, Object loginId, String tokenValue) {
} }
@Override @Override
public void doKickout(String loginType, Object loginId, String tokenValue) { public void doKickout(String loginType, Object loginId, String tokenValue) {
} }
@Override @Override
public void doReplaced(String loginType, Object loginId, String tokenValue) { public void doReplaced(String loginType, Object loginId, String tokenValue) {
} }
@Override @Override
public void doDisable(String loginType, Object loginId, String service, int level, long disableTime) { public void doDisable(String loginType, Object loginId, String service, int level, long disableTime) {
} }
@Override @Override
public void doUntieDisable(String loginType, Object loginId, String service) { public void doUntieDisable(String loginType, Object loginId, String service) {
} }
@Override @Override
public void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) { public void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) {
} }
@Override @Override
public void doCloseSafe(String loginType, String tokenValue, String service) { public void doCloseSafe(String loginType, String tokenValue, String service) {
} }
@Override @Override
public void doCreateSession(String id) { public void doCreateSession(String id) {
} }
@Override @Override
public void doLogoutSession(String id) { public void doLogoutSession(String id) {
} }
@Override @Override
@ -82,5 +82,9 @@ public class SaTokenListenerForSimple implements SaTokenListener {
} }
@Override
public void doTokenExpire(String tokenValue) {
}
} }