diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/SaManager.java b/sa-token-core/src/main/java/cn/dev33/satoken/SaManager.java index be721295..f762a28f 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/SaManager.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/SaManager.java @@ -23,7 +23,7 @@ import cn.dev33.satoken.temp.SaTempDefaultImpl; import cn.dev33.satoken.util.SaFoxUtil; /** - * 管理sa-token所有接口对象 + * 管理 Sa-Token 所有接口对象 * @author kong * */ diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/action/SaTokenAction.java b/sa-token-core/src/main/java/cn/dev33/satoken/action/SaTokenAction.java index 599e3224..0936d6ea 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/action/SaTokenAction.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/action/SaTokenAction.java @@ -6,7 +6,7 @@ import java.util.List; import cn.dev33.satoken.session.SaSession; /** - * sa-token逻辑代理接口 + * Sa-Token 逻辑代理接口 *
此接口将会代理框架内部的一些关键性逻辑,方便开发者进行按需重写
* @author kong * @@ -14,22 +14,22 @@ import cn.dev33.satoken.session.SaSession; public interface SaTokenAction { /** - * 根据一定的算法生成一个token + * 创建一个Token * @param loginId 账号id * @param loginType 账号类型 - * @return 一个token + * @return token */ public String createToken(Object loginId, String loginType); /** - * 根据 SessionId 创建一个 Session + * 创建一个Session * @param sessionId Session的Id * @return 创建后的Session */ public SaSession createSession(String sessionId); /** - * 指定集合是否包含指定元素(模糊匹配) + * 判断:集合中是否包含指定元素(模糊匹配) * @param list 集合 * @param element 元素 * @return 是否包含 diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/action/SaTokenActionDefaultImpl.java b/sa-token-core/src/main/java/cn/dev33/satoken/action/SaTokenActionDefaultImpl.java index ceda0101..3595de88 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/action/SaTokenActionDefaultImpl.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/action/SaTokenActionDefaultImpl.java @@ -9,19 +9,20 @@ import cn.dev33.satoken.SaManager; import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaCheckRole; +import cn.dev33.satoken.annotation.SaCheckSafe; import cn.dev33.satoken.session.SaSession; import cn.dev33.satoken.util.SaFoxUtil; import cn.dev33.satoken.util.SaTokenConsts; /** - * 对 SaTokenAction 接口的默认实现 + * Sa-Token 逻辑代理接口 [默认实现类] * @author kong * */ public class SaTokenActionDefaultImpl implements SaTokenAction { /** - * 根据一定的算法生成一个token + * 创建一个Token */ @Override public String createToken(Object loginId, String loginType) { @@ -56,7 +57,7 @@ public class SaTokenActionDefaultImpl implements SaTokenAction { } /** - * 根据 SessionId 创建一个 Session + * 创建一个Session */ @Override public SaSession createSession(String sessionId) { @@ -64,11 +65,12 @@ public class SaTokenActionDefaultImpl implements SaTokenAction { } /** - * 指定集合是否包含指定元素(模糊匹配) + * 判断:集合中是否包含指定元素(模糊匹配) */ @Override public boolean hasElement(List可标注在类上,其效果等同于标注在此类的所有方法上 + * 登录校验:只有登录之后才能进入该方法 + *
可标注在函数、类上(效果等同于标注在此类的所有方法上) * @author kong * */ diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/annotation/SaCheckPermission.java b/sa-token-core/src/main/java/cn/dev33/satoken/annotation/SaCheckPermission.java index d9b18906..b1c72b71 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/annotation/SaCheckPermission.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/annotation/SaCheckPermission.java @@ -6,8 +6,8 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * 权限校验:标注在一个方法上,当前会话必须具有指定权限才能进入该方法 - *
可标注在类上,其效果等同于标注在此类的所有方法上 + * 权限校验:必须具有指定权限才能进入该方法 + *
可标注在函数、类上(效果等同于标注在此类的所有方法上) * @author kong * */ diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/annotation/SaCheckRole.java b/sa-token-core/src/main/java/cn/dev33/satoken/annotation/SaCheckRole.java index dc925783..485f3174 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/annotation/SaCheckRole.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/annotation/SaCheckRole.java @@ -6,8 +6,8 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * 角色校验:标注在一个方法上,当前会话必须具有指定角色标识才能进入该方法 - *
可标注在类上,其效果等同于标注在此类的所有方法上 + * 角色校验:必须具有指定角色标识才能进入该方法 + *
可标注在函数、类上(效果等同于标注在此类的所有方法上) * @author kong * */ diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/annotation/SaCheckSafe.java b/sa-token-core/src/main/java/cn/dev33/satoken/annotation/SaCheckSafe.java new file mode 100644 index 00000000..ba559d78 --- /dev/null +++ b/sa-token-core/src/main/java/cn/dev33/satoken/annotation/SaCheckSafe.java @@ -0,0 +1,18 @@ +package cn.dev33.satoken.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 二级认证校验:必须二级认证之后才能进入该方法 + *
可标注在函数、类上(效果等同于标注在此类的所有方法上) + * @author kong + * + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD, ElementType.TYPE }) +public @interface SaCheckSafe { + +} diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/config/SaTokenConfig.java b/sa-token-core/src/main/java/cn/dev33/satoken/config/SaTokenConfig.java index 3d811e16..22a60311 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/config/SaTokenConfig.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/config/SaTokenConfig.java @@ -1,7 +1,7 @@ package cn.dev33.satoken.config; /** - * sa-token 配置类 Model + * Sa-Token 配置类 Model *
* 你可以通过yml、properties、java代码等形式配置本类参数,具体请查阅官方文档: http://sa-token.dev33.cn/ * diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/config/SaTokenConfigFactory.java b/sa-token-core/src/main/java/cn/dev33/satoken/config/SaTokenConfigFactory.java index 08180769..1c7f195a 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/config/SaTokenConfigFactory.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/config/SaTokenConfigFactory.java @@ -8,7 +8,7 @@ import java.util.Map; import java.util.Properties; /** - * sa-token配置文件的构建工厂类 + * Sa-Token配置文件的构建工厂类 *
* 只有在非IOC环境下才会用到此类
*
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/context/SaTokenContextForThreadLocal.java b/sa-token-core/src/main/java/cn/dev33/satoken/context/SaTokenContextForThreadLocal.java
index cab224cd..02dd2c68 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/context/SaTokenContextForThreadLocal.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/context/SaTokenContextForThreadLocal.java
@@ -5,7 +5,7 @@ import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.context.model.SaStorage;
/**
- * 上下文环境 [ThreadLocal版本]
+ * Sa-Token 上下文处理器 [ThreadLocal版本]
* @author kong
*
*/
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/context/SaTokenContextForThreadLocalStorage.java b/sa-token-core/src/main/java/cn/dev33/satoken/context/SaTokenContextForThreadLocalStorage.java
index d8303414..4c4813bc 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/context/SaTokenContextForThreadLocalStorage.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/context/SaTokenContextForThreadLocalStorage.java
@@ -6,19 +6,19 @@ import cn.dev33.satoken.context.model.SaStorage;
import cn.dev33.satoken.exception.SaTokenException;
/**
- * 基于ThreadLocal的上下文对象存储器
+ * Sa-Token 上下文处理器 [ThreadLocal版本] ---- 对象存储器
* @author kong
*
*/
public class SaTokenContextForThreadLocalStorage {
/**
- * 基于 ThreadLocal 的上下文
+ * 基于 ThreadLocal 的 [Box存储器]
*/
- static ThreadLocal 你可以通过实现此接口在用户登陆、退出等关键性操作时进行一些AOP操作
* @author kong
*
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/router/SaRouteFunction.java b/sa-token-core/src/main/java/cn/dev33/satoken/router/SaRouteFunction.java
index cf644f2b..7ec2af19 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/router/SaRouteFunction.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/router/SaRouteFunction.java
@@ -4,7 +4,7 @@ import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.context.model.SaResponse;
/**
- * 执行验证方法的辅助类
+ * 路由拦截器验证方法Lambda
*
* @author kong
*
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/router/SaRouter.java b/sa-token-core/src/main/java/cn/dev33/satoken/router/SaRouter.java
index 26d06ae8..0672dbd6 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/router/SaRouter.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/router/SaRouter.java
@@ -10,7 +10,7 @@ import cn.dev33.satoken.fun.IsRunFunction;
import cn.dev33.satoken.fun.SaFunction;
/**
- * 对路由匹配符相关操作的封装工具类
+ * 路由匹配操作工具类
* @author kong
*
*/
@@ -19,9 +19,9 @@ public class SaRouter {
// -------------------- 路由匹配相关 --------------------
/**
- * 校验指定路由匹配符是否可以匹配成功指定路径
+ * 路由匹配
* @param pattern 路由匹配符
- * @param path 需要匹配的路径
+ * @param path 被匹配的路由
* @return 是否匹配成功
*/
public static boolean isMatch(String pattern, String path) {
@@ -29,9 +29,9 @@ public class SaRouter {
}
/**
- * 校验指定路由匹配符是否可以匹配成功指定路径
- * @param patterns 路由匹配符
- * @param path 需要匹配的路径集合
+ * 路由匹配
+ * @param patterns 路由匹配符集合
+ * @param path 被匹配的路由
* @return 是否匹配成功
*/
public static boolean isMatch(List
* 如果开发者没有实现StpInterface接口,则使用此默认实现
*
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java
index a4aaa05a..883ef28b 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java
@@ -9,6 +9,7 @@ import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
+import cn.dev33.satoken.annotation.SaCheckSafe;
import cn.dev33.satoken.annotation.SaMode;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.context.SaHolder;
@@ -20,6 +21,7 @@ import cn.dev33.satoken.exception.DisableLoginException;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
+import cn.dev33.satoken.exception.NotSafeException;
import cn.dev33.satoken.fun.SaFunction;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.TokenSign;
@@ -66,7 +68,7 @@ public class StpLogic {
}
- // =================== 获取token 相关 ===================
+ // ------------------- 获取token 相关 -------------------
/**
* 返回token名称
@@ -77,7 +79,7 @@ public class StpLogic {
}
/**
- * 创建一个tokenValue
+ * 创建一个TokenValue
* @param loginId loginId
* @return 生成的tokenValue
*/
@@ -86,14 +88,16 @@ public class StpLogic {
}
/**
- * 在当前会话写入当前tokenValue
+ * 在当前会话写入当前TokenValue
* @param tokenValue token值
* @param cookieTimeout Cookie存活时间(秒)
*/
public void setTokenValue(String tokenValue, int cookieTimeout){
SaTokenConfig config = getConfig();
+
// 将token保存到[存储器]里
SaStorage storage = SaHolder.getStorage();
+
// 判断是否配置了token前缀
String tokenPrefix = config.getTokenPrefix();
if(SaFoxUtil.isEmpty(tokenPrefix)) {
@@ -111,7 +115,7 @@ public class StpLogic {
}
/**
- * 获取当前tokenValue
+ * 获取当前TokenValue
* @return 当前tokenValue
*/
public String getTokenValue(){
@@ -155,7 +159,7 @@ public class StpLogic {
}
/**
- * 获取当前会话的token信息
+ * 获取当前会话的Token信息
* @return token信息
*/
public SaTokenInfo getTokenInfo() {
@@ -174,7 +178,7 @@ public class StpLogic {
}
- // =================== 登录相关操作 ===================
+ // ------------------- 登录相关操作 -------------------
// 登录与注销
@@ -279,7 +283,7 @@ public class StpLogic {
}
/**
- * 当前会话注销登录
+ * 会话注销
*/
public void logout() {
// 如果连token都没有,那么无需执行任何操作
@@ -295,7 +299,7 @@ public class StpLogic {
}
/**
- * 指定token的会话注销登录
+ * 会话注销,根据指定Token
* @param tokenValue 指定token
*/
public void logoutByTokenValue(String tokenValue) {
@@ -327,7 +331,7 @@ public class StpLogic {
}
/**
- * 指定账号id的会话注销登录(踢人下线)
+ * 会话注销,根据账号id (踢人下线)
* 当对方再次访问系统时,会抛出NotLoginException异常,场景值=-2
* @param loginId 账号id
*/
@@ -336,7 +340,7 @@ public class StpLogic {
}
/**
- * 指定账号id指定设备的会话注销登录(踢人下线)
+ * 会话注销,根据账号id & 设备标识 (踢人下线)
* 当对方再次访问系统时,会抛出NotLoginException异常,场景值=-2
* @param loginId 账号id
* @param device 设备标识 (填null代表所有注销设备)
@@ -368,54 +372,10 @@ public class StpLogic {
session.logoutByTokenSignCountToZero();
}
- /**
- * 封禁指定账号
- * 此方法不会直接将此账号id踢下线,而是在对方再次登录时抛出`DisableLoginException`异常
- * @param loginId 指定账号id
- * @param disableTime 封禁时间, 单位: 秒 (-1=永久封禁)
- */
- public void disable(Object loginId, long disableTime) {
- // 标注为已被封禁
- SaManager.getSaTokenDao().set(splicingKeyDisable(loginId), DisableLoginException.BE_VALUE, disableTime);
-
- // $$ 通知监听器
- SaManager.getSaTokenListener().doDisable(loginType, loginId, disableTime);
- }
-
- /**
- * 指定账号是否已被封禁 (true=已被封禁, false=未被封禁)
- * @param loginId 账号id
- * @return see note
- */
- public boolean isDisable(Object loginId) {
- return SaManager.getSaTokenDao().get(splicingKeyDisable(loginId)) != null;
- }
-
- /**
- * 获取指定账号剩余封禁时间,单位:秒(-1=永久封禁,-2=未被封禁)
- * @param loginId 账号id
- * @return see note
- */
- public long getDisableTime(Object loginId) {
- return SaManager.getSaTokenDao().getTimeout(splicingKeyDisable(loginId));
- }
-
- /**
- * 解封指定账号
- * @param loginId 账号id
- */
- public void untieDisable(Object loginId) {
- SaManager.getSaTokenDao().delete(splicingKeyDisable(loginId));
-
- // $$ 通知监听器
- SaManager.getSaTokenListener().doUntieDisable(loginType, loginId);
- }
-
-
// 查询相关
/**
- * 获取当前会话是否已经登录
+ * 当前会话是否已经登录
* @return 是否已登录
*/
public boolean isLogin() {
@@ -472,7 +432,7 @@ public class StpLogic {
}
/**
- * 获取当前会话登录id, 如果未登录,则返回默认值
+ * 获取当前会话账号id, 如果未登录,则返回默认值
* @param 在配置为允许并发登录时,此方法只会返回队列的最后一个token,
* 如果你需要返回此账号id的所有token,请调用 getTokenValueListByLoginId
* @param loginId 账号id
@@ -1020,7 +980,7 @@ public class StpLogic {
}
/**
- * 获取指定loginId指定设备端的tokenValue
+ * 获取指定账号id指定设备端的tokenValue
* 在配置为允许并发登录时,此方法只会返回队列的最后一个token,
* 如果你需要返回此账号id的所有token,请调用 getTokenValueListByLoginId
* @param loginId 账号id
@@ -1033,7 +993,7 @@ public class StpLogic {
}
/**
- * 获取指定loginId的tokenValue集合
+ * 获取指定账号id的tokenValue集合
* @param loginId 账号id
* @return 此loginId的所有相关token
*/
@@ -1042,7 +1002,7 @@ public class StpLogic {
}
/**
- * 获取指定loginId指定设备端的tokenValue 集合
+ * 获取指定账号id指定设备端的tokenValue 集合
* @param loginId 账号id
* @param device 设备标识
* @return 此loginId的所有相关token
@@ -1065,7 +1025,7 @@ public class StpLogic {
}
/**
- * 返回当前token的登录设备
+ * 返回当前会话的登录设备
* @return 当前令牌的登录设备
*/
public String getLoginDevice() {
@@ -1094,10 +1054,10 @@ public class StpLogic {
}
- // =================== 会话管理 ===================
+ // ------------------- 会话管理 -------------------
/**
- * 根据条件查询token
+ * 根据条件查询Token
* @param keyword 关键字
* @param start 开始处索引 (-1代表查询所有)
* @param size 获取数量
@@ -1119,7 +1079,7 @@ public class StpLogic {
}
/**
- * 根据条件查询token专属Session的Id
+ * 根据条件查询Token专属Session的Id
* @param keyword 关键字
* @param start 开始处索引 (-1代表查询所有)
* @param size 获取数量
@@ -1130,90 +1090,7 @@ public class StpLogic {
}
- // =================== 返回相应key ===================
-
- /**
- * 获取key:客户端 tokenName
- * @return key
- */
- public String splicingKeyTokenName() {
- return getConfig().getTokenName();
- }
-
- /**
- * 获取key: tokenValue 持久化 token-id
- * @param tokenValue token值
- * @return key
- */
- public String splicingKeyTokenValue(String tokenValue) {
- return getConfig().getTokenName() + ":" + loginType + ":token:" + tokenValue;
- }
-
- /**
- * 获取key: session 持久化
- * @param loginId 账号id
- * @return key
- */
- public String splicingKeySession(Object loginId) {
- return getConfig().getTokenName() + ":" + loginType + ":session:" + loginId;
- }
-
- /**
- * 获取key: tokenValue的专属session
- * @param tokenValue token值
- * @return key
- */
- public String splicingKeyTokenSession(String tokenValue) {
- return getConfig().getTokenName() + ":" + loginType + ":token-session:" + tokenValue;
- }
-
- /**
- * 获取key: 指定token的最后操作时间 持久化
- * @param tokenValue token值
- * @return key
- */
- public String splicingKeyLastActivityTime(String tokenValue) {
- return getConfig().getTokenName() + ":" + loginType + ":last-activity:" + tokenValue;
- }
-
- /**
- * 在进行身份切换时,使用的存储key
- * @return key
- */
- public String splicingKeySwitch() {
- return SaTokenConsts.SWITCH_TO_SAVE_KEY + loginType;
- }
-
- /**
- * 如果token为本次请求新创建的,则以此字符串为key存储在当前request中
- * @return key
- */
- public String splicingKeyJustCreatedSave() {
- return SaTokenConsts.JUST_CREATED_SAVE_KEY + loginType;
- }
-
- /**
- * 拼接key: 账号封禁
- * @param loginId 账号id
- * @return key
- */
- public String splicingKeyDisable(Object loginId) {
- return getConfig().getTokenName() + ":" + loginType + ":disable:" + loginId;
- }
-
- // =================== Bean对象代理 ===================
-
- /**
- * 返回配置对象
- * @return 配置对象
- */
- public SaTokenConfig getConfig() {
- // 为什么再次代理一层? 为某些极端业务场景下[需要不同StpLogic不同配置]提供便利
- return SaManager.getConfig();
- }
-
-
- // =================== 其它方法 ===================
+ // ------------------- 其它方法 -------------------
/**
* 根据注解(@SaCheckLogin)鉴权
@@ -1249,11 +1126,65 @@ public class StpLogic {
}
}
+ /**
+ * 根据注解(@SaCheckSafe)鉴权
+ * @param at 注解对象
+ */
+ public void checkByAnnotation(SaCheckSafe at) {
+ this.checkSafe();
+ }
+
- // =================== 身份切换 ===================
+ // ------------------- 账号封禁 -------------------
/**
- * 临时切换身份为指定loginId
+ * 封禁指定账号
+ * 此方法不会直接将此账号id踢下线,而是在对方再次登录时抛出`DisableLoginException`异常
+ * @param loginId 指定账号id
+ * @param disableTime 封禁时间, 单位: 秒 (-1=永久封禁)
+ */
+ public void disable(Object loginId, long disableTime) {
+ // 标注为已被封禁
+ SaManager.getSaTokenDao().set(splicingKeyDisable(loginId), DisableLoginException.BE_VALUE, disableTime);
+
+ // $$ 通知监听器
+ SaManager.getSaTokenListener().doDisable(loginType, loginId, disableTime);
+ }
+
+ /**
+ * 指定账号是否已被封禁 (true=已被封禁, false=未被封禁)
+ * @param loginId 账号id
+ * @return see note
+ */
+ public boolean isDisable(Object loginId) {
+ return SaManager.getSaTokenDao().get(splicingKeyDisable(loginId)) != null;
+ }
+
+ /**
+ * 获取指定账号剩余封禁时间,单位:秒(-1=永久封禁,-2=未被封禁)
+ * @param loginId 账号id
+ * @return see note
+ */
+ public long getDisableTime(Object loginId) {
+ return SaManager.getSaTokenDao().getTimeout(splicingKeyDisable(loginId));
+ }
+
+ /**
+ * 解封指定账号
+ * @param loginId 账号id
+ */
+ public void untieDisable(Object loginId) {
+ SaManager.getSaTokenDao().delete(splicingKeyDisable(loginId));
+
+ // $$ 通知监听器
+ SaManager.getSaTokenListener().doUntieDisable(loginType, loginId);
+ }
+
+
+ // ------------------- 身份切换 -------------------
+
+ /**
+ * 临时切换身份为指定账号id
* @param loginId 指定loginId
*/
public void switchTo(Object loginId) {
@@ -1284,8 +1215,8 @@ public class StpLogic {
}
/**
- * 在一个代码段里方法内,临时切换身份为指定loginId
- * @param loginId 指定loginId
+ * 在一个代码段里方法内,临时切换身份为指定账号id
+ * @param loginId 指定账号id
* @param function 要执行的方法
*/
public void switchTo(Object loginId, SaFunction function) {
@@ -1298,6 +1229,142 @@ public class StpLogic {
endSwitch();
}
}
+
+
+ // ------------------- 二级认证 -------------------
+
+ /**
+ * 在当前会话 开启二级认证
+ * @param timeout 维持时间 (单位: 秒)
+ */
+ public void openSafe(long safeTime) {
+ long eff = System.currentTimeMillis() + safeTime * 1000;
+ getTokenSession().set(SaTokenConsts.SAFE_AUTH_SAVE_KEY, eff);
+ }
+
+ /**
+ * 当前会话 是否处于二级认证时间内
+ * @return true=二级认证已通过, false=尚未进行二级认证或认证已超时
+ */
+ public boolean isSafe() {
+ long eff = getTokenSession().get(SaTokenConsts.SAFE_AUTH_SAVE_KEY, 0L);
+ if(eff == 0 || eff < System.currentTimeMillis()) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 检查当前会话是否已通过二级认证,如未通过则抛出异常
+ */
+ public void checkSafe() {
+ if (isSafe() == false) {
+ throw new NotSafeException();
+ }
+ }
+
+ /**
+ * 获取当前会话的二级认证剩余有效时间 (单位: 秒, 返回-2代表尚未通过二级认证)
+ * @return
+ */
+ public long getSafeTime() {
+ long eff = getTokenSession().get(SaTokenConsts.SAFE_AUTH_SAVE_KEY, 0L);
+ if(eff == 0 || eff < System.currentTimeMillis()) {
+ return SaTokenDao.NOT_VALUE_EXPIRE;
+ }
+ return (eff - System.currentTimeMillis()) / 1000;
+ }
+
+ /**
+ * 在当前会话 结束二级认证
+ */
+ public void closeSafe() {
+ getTokenSession().delete(SaTokenConsts.SAFE_AUTH_SAVE_KEY);
+ }
+
+
+ // ------------------- 返回相应key -------------------
+
+ /**
+ * 拼接key:客户端 tokenName
+ * @return key
+ */
+ public String splicingKeyTokenName() {
+ return getConfig().getTokenName();
+ }
+
+ /**
+ * 拼接key: tokenValue 持久化 token-id
+ * @param tokenValue token值
+ * @return key
+ */
+ public String splicingKeyTokenValue(String tokenValue) {
+ return getConfig().getTokenName() + ":" + loginType + ":token:" + tokenValue;
+ }
+
+ /**
+ * 拼接key: Session 持久化
+ * @param loginId 账号id
+ * @return key
+ */
+ public String splicingKeySession(Object loginId) {
+ return getConfig().getTokenName() + ":" + loginType + ":session:" + loginId;
+ }
+
+ /**
+ * 拼接key: tokenValue的专属session
+ * @param tokenValue token值
+ * @return key
+ */
+ public String splicingKeyTokenSession(String tokenValue) {
+ return getConfig().getTokenName() + ":" + loginType + ":token-session:" + tokenValue;
+ }
+
+ /**
+ * 拼接key: 指定token的最后操作时间 持久化
+ * @param tokenValue token值
+ * @return key
+ */
+ public String splicingKeyLastActivityTime(String tokenValue) {
+ return getConfig().getTokenName() + ":" + loginType + ":last-activity:" + tokenValue;
+ }
+
+ /**
+ * 在进行身份切换时,使用的存储key
+ * @return key
+ */
+ public String splicingKeySwitch() {
+ return SaTokenConsts.SWITCH_TO_SAVE_KEY + loginType;
+ }
+
+ /**
+ * 如果token为本次请求新创建的,则以此字符串为key存储在当前request中
+ * @return key
+ */
+ public String splicingKeyJustCreatedSave() {
+ return SaTokenConsts.JUST_CREATED_SAVE_KEY + loginType;
+ }
+
+ /**
+ * 拼接key: 账号封禁
+ * @param loginId 账号id
+ * @return key
+ */
+ public String splicingKeyDisable(Object loginId) {
+ return getConfig().getTokenName() + ":" + loginType + ":disable:" + loginId;
+ }
+
+
+ // ------------------- Bean对象代理 -------------------
+
+ /**
+ * 返回配置对象
+ * @return 配置对象
+ */
+ public SaTokenConfig getConfig() {
+ // 为什么再次代理一层? 为某些极端业务场景下[需要不同StpLogic不同配置]提供便利
+ return SaManager.getConfig();
+ }
}
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java
index 8cf4b464..d5ce4618 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java
@@ -41,7 +41,7 @@ public class StpUtil {
}
/**
- * 在当前会话写入当前tokenValue
+ * 在当前会话写入当前TokenValue
* @param tokenValue token值
* @param cookieTimeout Cookie存活时间(秒)
*/
@@ -50,7 +50,7 @@ public class StpUtil {
}
/**
- * 获取当前tokenValue
+ * 获取当前TokenValue
* @return 当前tokenValue
*/
public static String getTokenValue() {
@@ -58,7 +58,7 @@ public class StpUtil {
}
/**
- * 获取当前会话的token信息
+ * 获取当前会话的Token信息
* @return token信息
*/
public static SaTokenInfo getTokenInfo() {
@@ -104,14 +104,14 @@ public class StpUtil {
}
/**
- * 当前会话注销登录
+ * 会话注销
*/
public static void logout() {
stpLogic.logout();
}
/**
- * 指定token的会话注销登录
+ * 会话注销,根据指定Token
* @param tokenValue 指定token
*/
public static void logoutByTokenValue(String tokenValue) {
@@ -119,7 +119,7 @@ public class StpUtil {
}
/**
- * 指定账号id的会话注销登录(踢人下线)
+ * 会话注销,根据账号id (踢人下线)
* 当对方再次访问系统时,会抛出NotLoginException异常,场景值=-2
* @param loginId 账号id
*/
@@ -128,7 +128,7 @@ public class StpUtil {
}
/**
- * 指定账号id指定设备的会话注销登录(踢人下线)
+ * 会话注销,根据账号id & 设备标识 (踢人下线)
* 当对方再次访问系统时,会抛出NotLoginException异常,场景值=-2
* @param loginId 账号id
* @param device 设备标识
@@ -137,53 +137,17 @@ public class StpUtil {
stpLogic.logoutByLoginId(loginId, device);
}
- /**
- * 封禁指定账号
- * 此方法不会直接将此账号id踢下线,而是在对方再次登录时抛出`DisableLoginException`异常
- * @param loginId 指定账号id
- * @param disableTime 封禁时间, 单位: 秒 (-1=永久封禁)
- */
- public static void disable(Object loginId, long disableTime) {
- stpLogic.disable(loginId, disableTime);
- }
-
- /**
- * 指定账号是否已被封禁 (true=已被封禁, false=未被封禁)
- * @param loginId 账号id
- * @return see note
- */
- public static boolean isDisable(Object loginId) {
- return stpLogic.isDisable(loginId);
- }
-
- /**
- * 获取指定账号剩余封禁时间,单位:秒(-1=永久封禁,-2=未被封禁)
- * @param loginId 账号id
- * @return see note
- */
- public static long getDisableTime(Object loginId) {
- return stpLogic.getDisableTime(loginId);
- }
-
- /**
- * 解封指定账号
- * @param loginId 账号id
- */
- public static void untieDisable(Object loginId) {
- stpLogic.untieDisable(loginId);
- }
-
// 查询相关
- /**
- * 获取当前会话是否已经登录
+ /**
+ * 当前会话是否已经登录
* @return 是否已登录
*/
public static boolean isLogin() {
return stpLogic.isLogin();
}
- /**
+ /**
* 检验当前会话是否已经登录,如未登录,则抛出异常
*/
public static void checkLogin() {
@@ -199,7 +163,7 @@ public class StpUtil {
}
/**
- * 获取当前会话登录id, 如果未登录,则返回默认值
+ * 获取当前会话账号id, 如果未登录,则返回默认值
* @param 在配置为允许并发登录时,此方法只会返回队列的最后一个token,
* 如果你需要返回此账号id的所有token,请调用 getTokenValueListByLoginId
* @param loginId 账号id
@@ -479,7 +443,7 @@ public class StpUtil {
}
/**
- * 获取指定loginId指定设备端的tokenValue
+ * 获取指定账号id指定设备端的tokenValue
* 在配置为允许并发登录时,此方法只会返回队列的最后一个token,
* 如果你需要返回此账号id的所有token,请调用 getTokenValueListByLoginId
* @param loginId 账号id
@@ -490,8 +454,8 @@ public class StpUtil {
return stpLogic.getTokenValueByLoginId(loginId, device);
}
- /**
- * 获取指定loginId的tokenValue集合
+ /**
+ * 获取指定账号id的tokenValue集合
* @param loginId 账号id
* @return 此loginId的所有相关token
*/
@@ -499,8 +463,8 @@ public class StpUtil {
return stpLogic.getTokenValueListByLoginId(loginId);
}
- /**
- * 获取指定loginId指定设备端的tokenValue集合
+ /**
+ * 获取指定账号id指定设备端的tokenValue 集合
* @param loginId 账号id
* @param device 设备标识
* @return 此loginId的所有相关token
@@ -510,7 +474,7 @@ public class StpUtil {
}
/**
- * 返回当前token的登录设备
+ * 返回当前会话的登录设备
* @return 当前令牌的登录设备
*/
public static String getLoginDevice() {
@@ -521,7 +485,7 @@ public class StpUtil {
// =================== 会话管理 ===================
/**
- * 根据条件查询token
+ * 根据条件查询Token
* @param keyword 关键字
* @param start 开始处索引 (-1代表查询所有)
* @param size 获取数量
@@ -543,7 +507,7 @@ public class StpUtil {
}
/**
- * 根据条件查询token专属Session的Id
+ * 根据条件查询Token专属Session的Id
* @param keyword 关键字
* @param start 开始处索引 (-1代表查询所有)
* @param size 获取数量
@@ -552,12 +516,51 @@ public class StpUtil {
public static List 此方法不会直接将此账号id踢下线,而是在对方再次登录时抛出`DisableLoginException`异常
+ * @param loginId 指定账号id
+ * @param disableTime 封禁时间, 单位: 秒 (-1=永久封禁)
+ */
+ public static void disable(Object loginId, long disableTime) {
+ stpLogic.disable(loginId, disableTime);
+ }
+
+ /**
+ * 指定账号是否已被封禁 (true=已被封禁, false=未被封禁)
+ * @param loginId 账号id
+ * @return see note
+ */
+ public static boolean isDisable(Object loginId) {
+ return stpLogic.isDisable(loginId);
+ }
+
+ /**
+ * 获取指定账号剩余封禁时间,单位:秒(-1=永久封禁,-2=未被封禁)
+ * @param loginId 账号id
+ * @return see note
+ */
+ public static long getDisableTime(Object loginId) {
+ return stpLogic.getDisableTime(loginId);
+ }
+
+ /**
+ * 解封指定账号
+ * @param loginId 账号id
+ */
+ public static void untieDisable(Object loginId) {
+ stpLogic.untieDisable(loginId);
+ }
+
+
// =================== 身份切换 ===================
/**
- * 临时切换身份为指定loginId
+ * 临时切换身份为指定账号id
* @param loginId 指定loginId
*/
public static void switchTo(Object loginId) {
@@ -580,8 +583,8 @@ public class StpUtil {
}
/**
- * 在一个代码段里方法内,临时切换身份为指定loginId
- * @param loginId 指定loginId
+ * 在一个代码段里方法内,临时切换身份为指定账号id
+ * @param loginId 指定账号id
* @param function 要执行的方法
*/
public static void switchTo(Object loginId, SaFunction function) {
@@ -589,6 +592,47 @@ public class StpUtil {
}
+ // ------------------- 二级认证 -------------------
+
+ /**
+ * 在当前会话 开启二级认证
+ * @param timeout 维持时间 (单位: 秒)
+ */
+ public static void openSafe(long safeTime) {
+ stpLogic.openSafe(safeTime);
+ }
+
+ /**
+ * 当前会话 是否处于二级认证时间内
+ * @return true=二级认证已通过, false=尚未进行二级认证或认证已超时
+ */
+ public static boolean isSafe() {
+ return stpLogic.isSafe();
+ }
+
+ /**
+ * 检查当前会话是否已通过二级认证,如未通过则抛出异常
+ */
+ public static void checkSafe() {
+ stpLogic.checkSafe();
+ }
+
+ /**
+ * 获取当前会话的二级认证剩余有效时间 (单位: 秒, 返回-2代表尚未通过二级认证)
+ * @return
+ */
+ public static long getSafeTime() {
+ return stpLogic.getSafeTime();
+ }
+
+ /**
+ * 在当前会话 结束二级认证
+ */
+ public static void closeSafe() {
+ stpLogic.closeSafe();
+ }
+
+
// =================== 历史API,兼容旧版本 ===================
/**
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/util/SaFoxUtil.java b/sa-token-core/src/main/java/cn/dev33/satoken/util/SaFoxUtil.java
index 312afcc0..42cee80e 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/util/SaFoxUtil.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/util/SaFoxUtil.java
@@ -18,7 +18,7 @@ import java.util.regex.Pattern;
public class SaFoxUtil {
/**
- * 打印 sa-token 版本字符画
+ * 打印 Sa-Token 版本字符画
*/
public static void printSaToken() {
String str = "____ ____ ___ ____ _ _ ____ _ _ \r\n" + "[__ |__| __ | | | |_/ |___ |\\ | \r\n"
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/util/SaTokenConsts.java b/sa-token-core/src/main/java/cn/dev33/satoken/util/SaTokenConsts.java
index af0123bf..5e0baf3c 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/util/SaTokenConsts.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/util/SaTokenConsts.java
@@ -1,7 +1,7 @@
package cn.dev33.satoken.util;
/**
- * sa-token常量类
+ * Sa-Token常量类
* @author kong
*
*/
@@ -11,17 +11,17 @@ public class SaTokenConsts {
// =================== sa-token版本信息 ===================
/**
- * sa-token 当前版本号
+ * Sa-Token 当前版本号
*/
public static final String VERSION_NO = "v1.20.0";
/**
- * sa-token 开源地址
+ * Sa-Token 开源地址
*/
public static final String GITHUB_URL = "https://github.com/dromara/sa-token";
/**
- * sa-token 开发文档地址
+ * Sa-Token 开发文档地址
*/
public static final String DEV_DOC_URL = "http://sa-token.dev33.cn";
@@ -47,36 +47,41 @@ public class SaTokenConsts {
*/
public static final String SWITCH_TO_SAVE_KEY = "SWITCH_TO_SAVE_KEY_";
+ /**
+ * 常量key标记: 在进行Token二级验证时使用的key
+ */
+ public static final String SAFE_AUTH_SAVE_KEY = "SAFE_AUTH_SAVE_KEY_";
+
// =================== token-style 相关 ===================
/**
- * token风格: uuid
+ * Token风格: uuid
*/
public static final String TOKEN_STYLE_UUID = "uuid";
/**
- * token风格: 简单uuid (不带下划线)
+ * Token风格: 简单uuid (不带下划线)
*/
public static final String TOKEN_STYLE_SIMPLE_UUID = "simple-uuid";
/**
- * token风格: 32位随机字符串
+ * Token风格: 32位随机字符串
*/
public static final String TOKEN_STYLE_RANDOM_32 = "random-32";
/**
- * token风格: 64位随机字符串
+ * Token风格: 64位随机字符串
*/
public static final String TOKEN_STYLE_RANDOM_64 = "random-64";
/**
- * token风格: 128位随机字符串
+ * Token风格: 128位随机字符串
*/
public static final String TOKEN_STYLE_RANDOM_128 = "random-128";
/**
- * token风格: tik风格 (2_14_16)
+ * Token风格: tik风格 (2_14_16)
*/
public static final String TOKEN_STYLE_TIK = "tik";
@@ -84,7 +89,7 @@ public class SaTokenConsts {
// =================== 其它 ===================
/**
- * 连接token前缀和token值的字符
+ * 连接Token前缀和Token值的字符
*/
public static final String TOKEN_CONNECTOR_CHAT = " ";
diff --git a/sa-token-demo/sa-token-demo-jwt/src/main/java/com/pj/test/TestJwtController.java b/sa-token-demo/sa-token-demo-jwt/src/main/java/com/pj/test/TestJwtController.java
index d11014b5..6111c13b 100644
--- a/sa-token-demo/sa-token-demo-jwt/src/main/java/com/pj/test/TestJwtController.java
+++ b/sa-token-demo/sa-token-demo-jwt/src/main/java/com/pj/test/TestJwtController.java
@@ -60,9 +60,9 @@ public class TestJwtController {
System.out.println("当前是否登录:" + StpUtil.isLogin());
System.out.println("当前登录账号session的id" + StpUtil.getSession().getId());
System.out.println("当前登录账号session的id" + StpUtil.getSession().getId());
- System.out.println("测试取值name:" + StpUtil.getSession().getAttribute("name"));
- StpUtil.getSession().setAttribute("name", new Date()); // 写入一个值
- System.out.println("测试取值name:" + StpUtil.getSession().getAttribute("name"));
+ System.out.println("测试取值name:" + StpUtil.getSession().get("name"));
+ StpUtil.getSession().set("name", new Date()); // 写入一个值
+ System.out.println("测试取值name:" + StpUtil.getSession().get("name"));
System.out.println( new ObjectMapper().writeValueAsString(StpUtil.getSession()));
return AjaxJson.getSuccess();
}
diff --git a/sa-token-demo/sa-token-demo-solon/src/main/java/com/pj/test/TestController.java b/sa-token-demo/sa-token-demo-solon/src/main/java/com/pj/test/TestController.java
index 5a88e4e9..d9b3c846 100644
--- a/sa-token-demo/sa-token-demo-solon/src/main/java/com/pj/test/TestController.java
+++ b/sa-token-demo/sa-token-demo-solon/src/main/java/com/pj/test/TestController.java
@@ -107,9 +107,9 @@ public class TestController {
System.out.println("当前是否登录:" + StpUtil.isLogin());
System.out.println("当前登录账号session的id" + StpUtil.getSession().getId());
System.out.println("当前登录账号session的id" + StpUtil.getSession().getId());
- System.out.println("测试取值name:" + StpUtil.getSession().getAttribute("name"));
- StpUtil.getSession().setAttribute("name", new Date()); // 写入一个值
- System.out.println("测试取值name:" + StpUtil.getSession().getAttribute("name"));
+ System.out.println("测试取值name:" + StpUtil.getSession().get("name"));
+ StpUtil.getSession().set("name", new Date()); // 写入一个值
+ System.out.println("测试取值name:" + StpUtil.getSession().get("name"));
System.out.println( ONode.stringify(StpUtil.getSession()));
return AjaxJson.getSuccess();
}
@@ -120,10 +120,10 @@ public class TestController {
System.out.println("======================= 进入方法,测试自定义session接口 ========================= ");
// 自定义session就是无需登录也可以使用 的session :比如拿用户的手机号当做 key, 来获取 session
System.out.println("自定义 session的id为:" + SaSessionCustomUtil.getSessionById("1895544896").getId());
- System.out.println("测试取值name:" + SaSessionCustomUtil.getSessionById("1895544896").getAttribute("name"));
- SaSessionCustomUtil.getSessionById("1895544896").setAttribute("name", "张三"); // 写入值
- System.out.println("测试取值name:" + SaSessionCustomUtil.getSessionById("1895544896").getAttribute("name"));
- System.out.println("测试取值name:" + SaSessionCustomUtil.getSessionById("1895544896").getAttribute("name"));
+ System.out.println("测试取值name:" + SaSessionCustomUtil.getSessionById("1895544896").get("name"));
+ SaSessionCustomUtil.getSessionById("1895544896").set("name", "张三"); // 写入值
+ System.out.println("测试取值name:" + SaSessionCustomUtil.getSessionById("1895544896").get("name"));
+ System.out.println("测试取值name:" + SaSessionCustomUtil.getSessionById("1895544896").get("name"));
return AjaxJson.getSuccess();
}
@@ -135,9 +135,9 @@ public class TestController {
System.out.println("当前是否登录:" + StpUtil.isLogin());
System.out.println("当前token专属session: " + StpUtil.getTokenSession().getId());
- System.out.println("测试取值name:" + StpUtil.getTokenSession().getAttribute("name"));
- StpUtil.getTokenSession().setAttribute("name", "张三"); // 写入一个值
- System.out.println("测试取值name:" + StpUtil.getTokenSession().getAttribute("name"));
+ System.out.println("测试取值name:" + StpUtil.getTokenSession().get("name"));
+ StpUtil.getTokenSession().set("name", "张三"); // 写入一个值
+ System.out.println("测试取值name:" + StpUtil.getTokenSession().get("name"));
return AjaxJson.getSuccess();
}
diff --git a/sa-token-demo/sa-token-demo-springboot/pom.xml b/sa-token-demo/sa-token-demo-springboot/pom.xml
index bf88deda..996b20cd 100644
--- a/sa-token-demo/sa-token-demo-springboot/pom.xml
+++ b/sa-token-demo/sa-token-demo-springboot/pom.xml
@@ -59,11 +59,11 @@
-->
-
+
此函数设计已过时,未来版本可能移除此类,请及时更换为: session.set(key)
+ * 写入一个值
+ *
+ * @param key 名称
+ * @param value 值
+ */
+ @Deprecated
+ public void setAttribute(String key, Object value) {
+ dataMap.put(key, value);
+ update();
+ }
+
+ /**
+ * 此函数设计已过时,未来版本可能移除此类,请及时更换为: session.get(key)
+ * 取出一个值
+ *
+ * @param key 名称
+ * @return 值
+ */
+ @Deprecated
+ public Object getAttribute(String key) {
+ return dataMap.get(key);
+ }
+
+ /**
+ * 此函数设计已过时,未来版本可能移除此类,请及时更换为: session.get(key, defaultValue)
+ * 取值,并指定取不到值时的默认值
+ *
+ * @param key 名称
+ * @param defaultValue 取不到值的时候返回的默认值
+ * @return value
+ */
+ @Deprecated
+ public Object getAttribute(String key, Object defaultValue) {
+ Object value = getAttribute(key);
+ if (value != null) {
+ return value;
+ }
+ return defaultValue;
+ }
+
+ /**
+ * 此函数设计已过时,未来版本可能移除此类,请及时更换为: session.delete(key)
+ * 移除一个值
+ *
+ * @param key 要移除的值的名字
+ */
+ @Deprecated
+ public void removeAttribute(String key) {
+ dataMap.remove(key);
+ update();
+ }
+
+ /**
+ * 此函数设计已过时,未来版本可能移除此类,请及时更换为: session.clear()
+ * 清空所有值
+ */
+ @Deprecated
+ public void clearAttribute() {
+ dataMap.clear();
+ update();
+ }
+
+ /**
+ * 此函数设计已过时,未来版本可能移除此类,请及时更换为: session.has(key)
+ * 是否含有指定key
+ *
+ * @param key 是否含有指定值
+ * @return 是否含有
+ */
+ @Deprecated
+ public boolean containsAttribute(String key) {
+ return dataMap.containsKey(key);
+ }
+
+ /**
+ * 此函数设计已过时,未来版本可能移除此类,请及时更换为: session.keys()
+ * 返回当前session会话所有key
+ *
+ * @return 所有值的key列表
+ */
+ @Deprecated
+ public Set
-如需更多加密算法请提交pr
+
+如需更多加密算法,可参考 [Hutool-crypto: 加密](https://hutool.cn/docs/#/crypto/%E6%A6%82%E8%BF%B0)
+
diff --git a/sa-token-plugin/sa-token-dao-redis-jackson/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedisJackson.java b/sa-token-plugin/sa-token-dao-redis-jackson/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedisJackson.java
index b5e67896..a8766c8b 100644
--- a/sa-token-plugin/sa-token-dao-redis-jackson/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedisJackson.java
+++ b/sa-token-plugin/sa-token-dao-redis-jackson/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedisJackson.java
@@ -20,7 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import cn.dev33.satoken.util.SaFoxUtil;
/**
- * sa-token持久层的实现类, 基于redis (使用 jackson 序列化方式)
+ * Sa-Token持久层接口 [Redis版] (使用 jackson 序列化方式)
*
* @author kong
*
@@ -73,7 +73,7 @@ public class SaTokenDaoRedisJackson implements SaTokenDao {
/**
- * 根据key获取value,如果没有,则返回空
+ * 获取Value,如无返空
*/
@Override
public String get(String key) {
@@ -81,7 +81,7 @@ public class SaTokenDaoRedisJackson implements SaTokenDao {
}
/**
- * 写入指定key-value键值对,并设定过期时间(单位:秒)
+ * 写入Value,并设定存活时间 (单位: 秒)
*/
@Override
public void set(String key, String value, long timeout) {
@@ -94,7 +94,7 @@ public class SaTokenDaoRedisJackson implements SaTokenDao {
}
/**
- * 修改指定key-value键值对 (过期时间不变)
+ * 修修改指定key-value键值对 (过期时间不变)
*/
@Override
public void update(String key, String value) {
@@ -107,7 +107,7 @@ public class SaTokenDaoRedisJackson implements SaTokenDao {
}
/**
- * 删除一个指定的key
+ * 删除Value
*/
@Override
public void delete(String key) {
@@ -115,7 +115,7 @@ public class SaTokenDaoRedisJackson implements SaTokenDao {
}
/**
- * 根据key获取value,如果没有,则返回空
+ * 获取Value的剩余存活时间 (单位: 秒)
*/
@Override
public long getTimeout(String key) {
@@ -123,7 +123,7 @@ public class SaTokenDaoRedisJackson implements SaTokenDao {
}
/**
- * 修改指定key的剩余存活时间 (单位: 秒)
+ * 修改Value的剩余存活时间 (单位: 秒)
*/
@Override
public void updateTimeout(String key, long timeout) {
@@ -144,7 +144,7 @@ public class SaTokenDaoRedisJackson implements SaTokenDao {
/**
- * 根据key获取Object,如果没有,则返回空
+ * 获取Object,如无返空
*/
@Override
public Object getObject(String key) {
@@ -152,7 +152,7 @@ public class SaTokenDaoRedisJackson implements SaTokenDao {
}
/**
- * 写入指定键值对,并设定过期时间 (单位: 秒)
+ * 写入Object,并设定存活时间 (单位: 秒)
*/
@Override
public void setObject(String key, Object object, long timeout) {
@@ -165,7 +165,7 @@ public class SaTokenDaoRedisJackson implements SaTokenDao {
}
/**
- * 修改指定键值对 (过期时间不变)
+ * 更新Object (过期时间不变)
*/
@Override
public void updateObject(String key, Object object) {
@@ -178,7 +178,7 @@ public class SaTokenDaoRedisJackson implements SaTokenDao {
}
/**
- * 删除一个指定的object
+ * 删除Object
*/
@Override
public void deleteObject(String key) {
@@ -186,7 +186,7 @@ public class SaTokenDaoRedisJackson implements SaTokenDao {
}
/**
- * 获取指定key的剩余存活时间 (单位: 秒)
+ * 获取Object的剩余存活时间 (单位: 秒)
*/
@Override
public long getObjectTimeout(String key) {
@@ -194,7 +194,7 @@ public class SaTokenDaoRedisJackson implements SaTokenDao {
}
/**
- * 修改指定key的剩余存活时间 (单位: 秒)
+ * 修改Object的剩余存活时间 (单位: 秒)
*/
@Override
public void updateObjectTimeout(String key, long timeout) {
diff --git a/sa-token-plugin/sa-token-dao-redis/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedis.java b/sa-token-plugin/sa-token-dao-redis/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedis.java
index 8ecbdc7b..781daa10 100644
--- a/sa-token-plugin/sa-token-dao-redis/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedis.java
+++ b/sa-token-plugin/sa-token-dao-redis/src/main/java/cn/dev33/satoken/dao/SaTokenDaoRedis.java
@@ -16,7 +16,7 @@ import org.springframework.stereotype.Component;
import cn.dev33.satoken.util.SaFoxUtil;
/**
- * sa-token持久层的实现类, 基于redis
+ * Sa-Token持久层接口 [Redis版 (使用JDK默认序列化方式)]
*
* @author kong
*
@@ -54,7 +54,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
/**
- * 根据key获取value,如果没有,则返回空
+ * 获取Value,如无返空
*/
@Override
public String get(String key) {
@@ -62,7 +62,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
}
/**
- * 写入指定key-value键值对,并设定过期时间(单位:秒)
+ * 写入Value,并设定存活时间 (单位: 秒)
*/
@Override
public void set(String key, String value, long timeout) {
@@ -88,7 +88,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
}
/**
- * 删除一个指定的key
+ * 删除Value
*/
@Override
public void delete(String key) {
@@ -96,7 +96,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
}
/**
- * 根据key获取value,如果没有,则返回空
+ * 获取Value的剩余存活时间 (单位: 秒)
*/
@Override
public long getTimeout(String key) {
@@ -104,7 +104,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
}
/**
- * 修改指定key的剩余存活时间 (单位: 秒)
+ * 修改Value的剩余存活时间 (单位: 秒)
*/
@Override
public void updateTimeout(String key, long timeout) {
@@ -124,7 +124,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
/**
- * 根据key获取Object,如果没有,则返回空
+ * 获取Object,如无返空
*/
@Override
public Object getObject(String key) {
@@ -132,7 +132,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
}
/**
- * 写入指定键值对,并设定过期时间 (单位: 秒)
+ * 写入Object,并设定存活时间 (单位: 秒)
*/
@Override
public void setObject(String key, Object object, long timeout) {
@@ -145,7 +145,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
}
/**
- * 修改指定键值对 (过期时间不变)
+ * 更新Object (过期时间不变)
*/
@Override
public void updateObject(String key, Object object) {
@@ -158,7 +158,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
}
/**
- * 删除一个指定的object
+ * 删除Object
*/
@Override
public void deleteObject(String key) {
@@ -166,7 +166,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
}
/**
- * 获取指定key的剩余存活时间 (单位: 秒)
+ * 获取Object的剩余存活时间 (单位: 秒)
*/
@Override
public long getObjectTimeout(String key) {
@@ -174,7 +174,7 @@ public class SaTokenDaoRedis implements SaTokenDao {
}
/**
- * 修改指定key的剩余存活时间 (单位: 秒)
+ * 修改Object的剩余存活时间 (单位: 秒)
*/
@Override
public void updateObjectTimeout(String key, long timeout) {
diff --git a/sa-token-plugin/sa-token-spring-aop/src/main/java/cn/dev33/satoken/aop/SaCheckAspect.java b/sa-token-plugin/sa-token-spring-aop/src/main/java/cn/dev33/satoken/aop/SaCheckAspect.java
index b01e7495..0ddfb0d9 100644
--- a/sa-token-plugin/sa-token-spring-aop/src/main/java/cn/dev33/satoken/aop/SaCheckAspect.java
+++ b/sa-token-plugin/sa-token-spring-aop/src/main/java/cn/dev33/satoken/aop/SaCheckAspect.java
@@ -33,7 +33,8 @@ public class SaCheckAspect {
public static final String POINTCUT_SIGN =
"@within(cn.dev33.satoken.annotation.SaCheckLogin) || @annotation(cn.dev33.satoken.annotation.SaCheckLogin) || "
+ "@within(cn.dev33.satoken.annotation.SaCheckRole) || @annotation(cn.dev33.satoken.annotation.SaCheckRole) || "
- + "@within(cn.dev33.satoken.annotation.SaCheckPermission) || @annotation(cn.dev33.satoken.annotation.SaCheckPermission)";
+ + "@within(cn.dev33.satoken.annotation.SaCheckPermission) || @annotation(cn.dev33.satoken.annotation.SaCheckPermission) || "
+ + "@within(cn.dev33.satoken.annotation.SaCheckSafe) || @annotation(cn.dev33.satoken.annotation.SaCheckSafe)";
/**
* 声明AOP签名
diff --git a/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/XPluginImp.java b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/XPluginImp.java
index 1fe41a55..8d712f6f 100644
--- a/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/XPluginImp.java
+++ b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/XPluginImp.java
@@ -10,6 +10,7 @@ import cn.dev33.satoken.action.SaTokenAction;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
+import cn.dev33.satoken.annotation.SaCheckSafe;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.listener.SaTokenListener;
@@ -29,6 +30,7 @@ public class XPluginImp implements Plugin {
Aop.context().beanAroundAdd(SaCheckPermission.class, SaTokenMethodInterceptor.INSTANCE);
Aop.context().beanAroundAdd(SaCheckRole.class, SaTokenMethodInterceptor.INSTANCE);
Aop.context().beanAroundAdd(SaCheckLogin.class, SaTokenMethodInterceptor.INSTANCE);
+ Aop.context().beanAroundAdd(SaCheckSafe.class, SaTokenMethodInterceptor.INSTANCE);
//集成初始化
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/SaTokenSpringBootStarterTest.java b/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/SaTokenSpringBootStarterTest.java
index 5440bb68..041eee64 100644
--- a/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/SaTokenSpringBootStarterTest.java
+++ b/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/SaTokenSpringBootStarterTest.java
@@ -183,5 +183,27 @@ public class SaTokenSpringBootStarterTest {
long timeout = SaTempUtil.getTimeout(token);
Assert.assertTrue(timeout > 195);
}
+
+ // 测试:二级认证
+ @Test
+ public void testSafe() throws InterruptedException {
+ // 登录
+ StpUtil.login(10001);
+ Assert.assertFalse(StpUtil.isSafe());
+
+ // 开启二级认证
+ StpUtil.openSafe(2);
+ Assert.assertTrue(StpUtil.isSafe());
+ Assert.assertTrue(StpUtil.getSafeTime() > 0);
+
+ // 自然结束
+ Thread.sleep(2500);
+ Assert.assertFalse(StpUtil.isSafe());
+
+ // 手动结束
+ StpUtil.openSafe(2);
+ StpUtil.closeSafe();
+ Assert.assertFalse(StpUtil.isSafe());
+ }
}