Sa-Token 监听器实现

This commit is contained in:
shengzhang 2021-04-17 02:54:43 +08:00
parent 078119e12c
commit 34a3f68ad8
11 changed files with 271 additions and 6 deletions

View File

@ -5,6 +5,8 @@ import java.util.Map;
import cn.dev33.satoken.action.SaTokenAction;
import cn.dev33.satoken.action.SaTokenActionDefaultImpl;
import cn.dev33.satoken.aop.SaTokenListener;
import cn.dev33.satoken.aop.SaTokenListenerDefaultImpl;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.config.SaTokenConfigFactory;
import cn.dev33.satoken.context.SaTokenContext;
@ -124,6 +126,24 @@ public class SaTokenManager {
return saTokenContext;
}
/**
* 监听器 Bean
*/
private static SaTokenListener saTokenListener;
public static void setSaTokenListener(SaTokenListener saTokenListener) {
SaTokenManager.saTokenListener = saTokenListener;
}
public static SaTokenListener getSaTokenListener() {
if (saTokenListener == null) {
synchronized (SaTokenManager.class) {
if (saTokenListener == null) {
setSaTokenListener(new SaTokenListenerDefaultImpl());
}
}
}
return saTokenListener;
}
/**
* StpLogic集合, 记录框架所有成功初始化的StpLogic
*/

View File

@ -0,0 +1,74 @@
package cn.dev33.satoken.aop;
import cn.dev33.satoken.stp.SaLoginModel;
/**
* Sa-Token的监听器
* <p> 你可以通过实现此接口在用户登陆退出等关键性操作时进行一些AOP操作
* @author kong
*
*/
public interface SaTokenListener {
/**
* 每次登录时触发
* @param loginKey 账号类别
* @param loginId 账号id
* @param loginModel 登录参数
*/
public void doLogin(String loginKey, Object loginId, SaLoginModel loginModel);
/**
* 每次注销时触发
* @param loginKey 账号类别
* @param loginId 账号id
* @param tokenValue token值
*/
public void doLogout(String loginKey, Object loginId, String tokenValue);
/**
* 每次被踢下线时触发
* @param loginKey 账号类别
* @param loginId 账号id
* @param tokenValue token值
* @param device 设备标识
*/
public void doLogoutByLoginId(String loginKey, Object loginId, String tokenValue, String device);
/**
* 每次被顶下线时触发
* @param loginKey 账号类别
* @param loginId 账号id
* @param tokenValue token值
* @param device 设备标识
*/
public void doReplaced(String loginKey, Object loginId, String tokenValue, String device);
/**
* 每次被封禁时触发
* @param loginKey 账号类别
* @param loginId 账号id
* @param disableTime 封禁时长单位:
*/
public void doDisable(String loginKey, Object loginId, long disableTime);
/**
* 每次被解封时触发
* @param loginKey 账号类别
* @param loginId 账号id
*/
public void doUntieDisable(String loginKey, Object loginId);
/**
* 每次创建Session时触发
* @param id SessionId
*/
public void doCreateSession(String id);
/**
* 每次注销Session时触发
* @param id SessionId
*/
public void doLogoutSession(String id);
}

View File

@ -0,0 +1,96 @@
package cn.dev33.satoken.aop;
import java.util.Date;
import cn.dev33.satoken.SaTokenManager;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.util.SaTokenInsideUtil;
/**
* Sa-Token 监听器的默认实现log打印
* @author kong
*
*/
public class SaTokenListenerDefaultImpl implements SaTokenListener {
/**
* 每次登录时触发
*/
@Override
public void doLogin(String loginKey, Object loginId, SaLoginModel loginModel) {
println("账号[" + loginId + "]登录成功");
}
/**
* 每次注销时触发
*/
@Override
public void doLogout(String loginKey, Object loginId, String tokenValue) {
println("账号[" + loginId + "]注销成功");
}
/**
* 每次被踢下线时触发
*/
@Override
public void doLogoutByLoginId(String loginKey, Object loginId, String tokenValue, String device) {
println("账号[" + loginId + "]被踢下线 (终端: " + device + ")");
}
/**
* 每次被顶下线时触发
*/
@Override
public void doReplaced(String loginKey, Object loginId, String tokenValue, String device) {
println("账号[" + loginId + "]被顶下线 (终端: " + device + ")");
}
/**
* 每次被封禁时触发
*/
@Override
public void doDisable(String loginKey, Object loginId, long disableTime) {
Date date = new Date(System.currentTimeMillis() + disableTime * 1000);
println("账号[" + loginId + "]被封禁 (解封时间: " + SaTokenInsideUtil.formatDate(date) + ")");
}
/**
* 每次被解封时触发
*/
@Override
public void doUntieDisable(String loginKey, Object loginId) {
println("账号[" + loginId + "]被解除封禁");
}
/**
* 每次创建Session时触发
*/
@Override
public void doCreateSession(String id) {
println("Session[" + id + "]创建成功");
}
/**
* 每次注销Session时触发
*/
@Override
public void doLogoutSession(String id) {
println("Session[" + id + "]注销成功");
}
/**
* 日志输出的前缀
*/
public static final String LOG_PREFIX = "SaLog -->: ";
/**
* 打印指定字符串
* @param str 字符串
*/
public void println(String str) {
if(SaTokenManager.getConfig().getIsLog()) {
System.out.println(LOG_PREFIX + str);
}
}
}

View File

@ -58,7 +58,9 @@ public class SaTokenConfig {
/** 是否在初始化配置时打印版本字符画 */
private Boolean isV = true;
/** 是否打印操作日志 */
private Boolean isLog = false;
/**
* @return token名称 (同时也是cookie名称)
@ -304,10 +306,23 @@ public class SaTokenConfig {
return this;
}
/**
* @return 是否打印操作日志
*/
public Boolean getIsLog() {
return isLog;
}
/**
* toString
* @param isLog 是否打印操作日志
*/
public SaTokenConfig setIsLog(Boolean isLog) {
this.isLog = isLog;
return this;
}
/**
* toString()
*/
@Override
public String toString() {
@ -316,8 +331,10 @@ public class SaTokenConfig {
+ isReadBody + ", isReadHead=" + isReadHead + ", isReadCookie=" + isReadCookie + ", tokenStyle="
+ tokenStyle + ", dataRefreshPeriod=" + dataRefreshPeriod + ", tokenSessionCheckLogin="
+ tokenSessionCheckLogin + ", autoRenew=" + autoRenew + ", cookieDomain=" + cookieDomain
+ ", tokenPrefix=" + tokenPrefix + ", isV=" + isV + "]";
+ ", tokenPrefix=" + tokenPrefix + ", isV=" + isV + ", isLog=" + isLog + "]";
}

View File

@ -34,6 +34,7 @@ public class SaSession implements Serializable {
* 构建一个Session对象
*/
public SaSession() {
this(null);
}
/**
@ -43,6 +44,8 @@ public class SaSession implements Serializable {
public SaSession(String id) {
this.id = id;
this.createTime = System.currentTimeMillis();
// $$ 通知监听器
SaTokenManager.getSaTokenListener().doCreateSession(id);
}
/**
@ -249,6 +252,8 @@ public class SaSession implements Serializable {
/** 注销Session (从持久库删除) */
public void logout() {
SaTokenManager.getSaTokenDao().deleteSession(this.id);
// $$ 通知监听器
SaTokenManager.getSaTokenListener().doLogoutSession(id);
}
/** 当Session上的tokenSign数量为零时注销会话 */

View File

@ -245,6 +245,8 @@ public class StpLogic {
clearLastActivity(tokenSign.getValue());
// 3. 清理user-session上的token签名记录
session.removeTokenSign(tokenSign.getValue());
// $$ 通知监听器
SaTokenManager.getSaTokenListener().doReplaced(loginKey, loginId, tokenSign.getValue(), tokenSign.getDevice());
}
}
}
@ -273,6 +275,9 @@ public class StpLogic {
// 在当前会话写入当前tokenValue
setTokenValue(tokenValue, loginModel.getCookieTimeout());
// $$ 通知监听器
SaTokenManager.getSaTokenListener().doLogin(loginKey, loginId, loginModel);
}
/**
@ -306,6 +311,9 @@ public class StpLogic {
}
SaTokenManager.getSaTokenDao().delete(splicingKeyTokenValue(tokenValue));
// $$ 通知监听器
SaTokenManager.getSaTokenListener().doLogout(loginKey, loginId, tokenValue);
// 3. 尝试清理账号session上的token签名 (如果为null或已被标记为异常, 那么无需继续执行 )
SaSession session = getSessionByLoginId(loginId, false);
if(session == null) {
@ -333,8 +341,8 @@ public class StpLogic {
* @param device 设备标识 (填null代表所有注销设备)
*/
public void logoutByLoginId(Object loginId, String device) {
// 1. 先获取这个账号的[id-session], 如果为null则不执行任何操作
SaSession session = getSessionByLoginId(loginId);
// 1. 先获取这个账号的[user-session], 如果为null则不执行任何操作
SaSession session = getSessionByLoginId(loginId, false);
if(session == null) {
return;
}
@ -351,6 +359,8 @@ public class StpLogic {
SaTokenManager.getSaTokenDao().update(splicingKeyTokenValue(tokenValue), NotLoginException.KICK_OUT);
// 4. 清理账号session上的token签名
session.removeTokenSign(tokenValue);
// $$ 通知监听器
SaTokenManager.getSaTokenListener().doLogoutByLoginId(loginKey, loginId, tokenValue, tokenSign.getDevice());
}
}
// 3. 尝试注销session
@ -364,7 +374,11 @@ public class StpLogic {
* @param disableTime 封禁时间, 单位: -1=永久封禁
*/
public void disable(Object loginId, long disableTime) {
// 标注为已被封禁
SaTokenManager.getSaTokenDao().set(splicingKeyDisable(loginId), DisableLoginException.BE_VALUE, disableTime);
// $$ 通知监听器
SaTokenManager.getSaTokenListener().doDisable(loginKey, loginId, disableTime);
}
/**
@ -391,6 +405,9 @@ public class StpLogic {
*/
public void untieDisable(Object loginId) {
SaTokenManager.getSaTokenDao().delete(splicingKeyDisable(loginId));
// $$ 通知监听器
SaTokenManager.getSaTokenListener().doUntieDisable(loginKey, loginId);
}

View File

@ -1,7 +1,9 @@
package cn.dev33.satoken.util;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
@ -63,6 +65,15 @@ public class SaTokenInsideUtil {
return System.currentTimeMillis() + "" + new Random().nextInt(Integer.MAX_VALUE);
}
/**
* 将日期格式化
* @param date 日期
* @return 格式化后的时间
*/
public static String formatDate(Date date){
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
}
/**
* 从集合里查询数据
*

View File

@ -241,6 +241,8 @@ public class TestController {
@RequestMapping("test")
public AjaxJson test() {
System.out.println("进来了");
StpUtil.disable(10001, 10002);
StpUtil.untieDisable(10001);
return AjaxJson.getSuccess("访问成功");
}

View File

@ -17,6 +17,8 @@ spring:
is-share: true
# token风格
token-style: uuid
# 是否输出操作日志
is-log: false
# redis配置

View File

@ -8,6 +8,7 @@ import org.springframework.util.PathMatcher;
import cn.dev33.satoken.SaTokenManager;
import cn.dev33.satoken.action.SaTokenAction;
import cn.dev33.satoken.aop.SaTokenListener;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.context.SaTokenContext;
import cn.dev33.satoken.context.SaTokenContextForThreadLocal;
@ -102,6 +103,15 @@ public class SaTokenSpringAutowired {
SaTokenManager.setSaTokenContext(saTokenContext);
}
/**
* 注入监听器Bean
*
* @param saTokenListener saTokenListener对象
*/
@Autowired(required = false)
public void setSaTokenListener(SaTokenListener saTokenListener) {
SaTokenManager.setSaTokenListener(saTokenListener);
}
/**
* 利用自动匹配特性获取SpringMVC框架内部使用的路由匹配器
*

View File

@ -8,6 +8,7 @@ import org.springframework.util.PathMatcher;
import cn.dev33.satoken.SaTokenManager;
import cn.dev33.satoken.action.SaTokenAction;
import cn.dev33.satoken.aop.SaTokenListener;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.context.SaTokenContext;
import cn.dev33.satoken.dao.SaTokenDao;
@ -93,6 +94,16 @@ public class SaTokenSpringAutowired {
SaTokenManager.setSaTokenContext(saTokenContext);
}
/**
* 注入监听器Bean
*
* @param saTokenListener saTokenListener对象
*/
@Autowired(required = false)
public void setSaTokenListener(SaTokenListener saTokenListener) {
SaTokenManager.setSaTokenListener(saTokenListener);
}
/**
* 利用自动匹配特性获取SpringMVC框架内部使用的路由匹配器
*