1
0
mirror of https://gitee.com/dromara/sa-token.git synced 2025-04-05 17:37:53 +08:00

新增登录时动态指定 active-timeout 能力

This commit is contained in:
click33 2023-06-06 06:18:52 +08:00
parent 48ba6da91a
commit 814a64907a
51 changed files with 835 additions and 475 deletions
sa-token-core/src/main/java/cn/dev33/satoken
sa-token-demo
sa-token-demo-case/src/main
sa-token-demo-jwt/src/main/resources
sa-token-demo-remember-me/server_project/src/main/resources
sa-token-demo-solon/src/main
java/com/pj/test
resources
sa-token-demo-springboot-redis/src/main/resources
sa-token-demo-springboot-redisson/src/main/resources
sa-token-demo-springboot/src/main
java/com/pj/test
resources
sa-token-demo-springboot3-redis/src/main/resources
sa-token-demo-test/src/main
sa-token-demo-webflux-springboot3/src/main/resources
sa-token-demo-webflux/src/main/resources
sa-token-demo-websocket-spring/src/main/resources
sa-token-demo-websocket/src/main/resources
sa-token-doc
sa-token-plugin/sa-token-jwt/src/main/java/cn/dev33/satoken/jwt
sa-token-starter
sa-token-jboot-plugin/src/test/java/cn/dev33/satoken/jboot/test
sa-token-jfinal-plugin/src/test/java/cn/dev33/satoken/jfinal/test
sa-token-solon-plugin/src/test/resources
sa-token-test
sa-token-jwt-test/src/test/resources
sa-token-springboot-test/src/test
java/cn/dev33/satoken
resources

View File

@ -25,7 +25,7 @@ import java.lang.annotation.Target;
*
* <p> 可标注在方法类上效果等同于标注在此类的所有方法上
*
* @author kong
* @author click33
* @since 1.10.0
*/
@Retention(RetentionPolicy.RUNTIME)

View File

@ -25,7 +25,7 @@ import java.lang.annotation.Target;
*
* <p> 可标注在方法类上效果等同于标注在此类的所有方法上
*
* @author kong
* @author click33
* @since 1.35.0
*/
@Retention(RetentionPolicy.RUNTIME)

View File

@ -15,6 +15,7 @@
*/
package cn.dev33.satoken.config;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.util.SaFoxUtil;
import java.io.Serializable;
@ -37,14 +38,19 @@ public class SaTokenConfig implements Serializable {
/** token 名称 (同时也是: cookie 名称、提交 token 时参数的名称、存储 token 时的 key 前缀) */
private String tokenName = "satoken";
/** token 有效期(单位:秒) 默认30天-1 代表永久 */
/** token 有效期(单位:秒) 默认30天-1 代表永久有效 */
private long timeout = 60 * 60 * 24 * 30;
/**
* token 最低活跃频率单位如果 token 超过此时间没有访问系统就会被冻结默认-1 代表不限制永不冻结
* 例如可以设置为 1800 代表 30 分钟内无操作就冻结
*/
private long activityTimeout = -1;
private long activeTimeout = -1;
/**
* 是否启用动态 activeTimeout 功能如不需要请设置为 false节省缓存请求次数
*/
private Boolean dynamicActiveTimeout = false;
/**
* 是否允许同一账号多地同时登录 true 时允许一起登录, false 时新登录挤掉旧登录
@ -102,7 +108,7 @@ public class SaTokenConfig implements Serializable {
private Boolean tokenSessionCheckLogin = true;
/**
* 是否打开自动续签 activityTimeout 如果此值为 true, 框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作
* 是否打开自动续签 activeTimeout 如果此值为 true, 框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作
*/
private Boolean autoRenew = true;
@ -189,14 +195,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return token 有效期单位 默认30天-1 代表永久
* @return token 有效期单位 默认30天-1 代表永久有效
*/
public long getTimeout() {
return timeout;
}
/**
* @param timeout token 有效期单位 默认30天-1 代表永久
* @param timeout token 有效期单位 默认30天-1 代表永久有效
* @return 对象自身
*/
public SaTokenConfig setTimeout(long timeout) {
@ -208,17 +214,33 @@ public class SaTokenConfig implements Serializable {
* @return token 最低活跃频率单位如果 token 超过此时间没有访问系统就会被冻结默认-1 代表不限制永不冻结
* 例如可以设置为 1800 代表 30 分钟内无操作就冻结
*/
public long getActivityTimeout() {
return activityTimeout;
public long getActiveTimeout() {
return activeTimeout;
}
/**
* @param activityTimeout token 最低活跃频率单位如果 token 超过此时间没有访问系统就会被冻结默认-1 代表不限制永不冻结
* @param activeTimeout token 最低活跃频率单位如果 token 超过此时间没有访问系统就会被冻结默认-1 代表不限制永不冻结
* 例如可以设置为 1800 代表 30 分钟内无操作就冻结
* @return 对象自身
*/
public SaTokenConfig setActivityTimeout(long activityTimeout) {
this.activityTimeout = activityTimeout;
public SaTokenConfig setActiveTimeout(long activeTimeout) {
this.activeTimeout = activeTimeout;
return this;
}
/**
* @return 是否启用动态 activeTimeout 功能如不需要请设置为 false节省缓存请求次数
*/
public Boolean getDynamicActiveTimeout() {
return dynamicActiveTimeout;
}
/**
* @param dynamicActiveTimeout 是否启用动态 activeTimeout 功能如不需要请设置为 false节省缓存请求次数
* @return 对象自身
*/
public SaTokenConfig setDynamicActiveTimeout(Boolean dynamicActiveTimeout) {
this.dynamicActiveTimeout = dynamicActiveTimeout;
return this;
}
@ -399,14 +421,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return 是否打开自动续签 activityTimeout 如果此值为 true, 框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作
* @return 是否打开自动续签 activeTimeout 如果此值为 true, 框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作
*/
public Boolean getAutoRenew() {
return autoRenew;
}
/**
* @param autoRenew 是否打开自动续签 activityTimeout 如果此值为 true, 框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作
* @param autoRenew 是否打开自动续签 activeTimeout 如果此值为 true, 框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作
* @return 对象自身
*/
public SaTokenConfig setAutoRenew(Boolean autoRenew) {
@ -633,7 +655,8 @@ public class SaTokenConfig implements Serializable {
return "SaTokenConfig ["
+ "tokenName=" + tokenName
+ ", timeout=" + timeout
+ ", activityTimeout=" + activityTimeout
+ ", activeTimeout=" + activeTimeout
+ ", dynamicActiveTimeout=" + dynamicActiveTimeout
+ ", isConcurrent=" + isConcurrent
+ ", isShare=" + isShare
+ ", maxLoginCount=" + maxLoginCount
@ -662,4 +685,29 @@ public class SaTokenConfig implements Serializable {
+ "]";
}
/**
* 请更改为 getActiveTimeout()
* @return token 最低活跃频率单位如果 token 超过此时间没有访问系统就会被冻结默认-1 代表不限制永不冻结
* 例如可以设置为 1800 代表 30 分钟内无操作就冻结
*/
@Deprecated
public long getActivityTimeout() {
System.err.println("配置项已过期请更换sa-token.activity-timeout -> sa-token.active-timeout");
return activeTimeout;
}
/**
* 请更改为 setActiveTimeout()
* @param activityTimeout token 最低活跃频率单位如果 token 超过此时间没有访问系统就会被冻结默认-1 代表不限制永不冻结
* 例如可以设置为 1800 代表 30 分钟内无操作就冻结
* @return 对象自身
*/
@Deprecated
public SaTokenConfig setActivityTimeout(long activityTimeout) {
System.err.println("配置项已过期请更换sa-token.activity-timeout -> sa-token.active-timeout");
this.activeTimeout = activityTimeout;
return this;
}
}

View File

@ -110,7 +110,7 @@ public interface SaTokenListener {
void doLogoutSession(String id);
/**
* 每次 Token 续期时触发注意 timeout 续期而不是 activity-timeout 续期
* 每次 Token 续期时触发注意 timeout 续期而不是 active-timeout 续期
*
* @param tokenValue token
* @param loginId 账号id

View File

@ -60,6 +60,14 @@ public class SaLoginConfig {
return create().setTimeout(timeout);
}
/**
* @param activeTimeout 指定此次登录 token 最低活跃频率单位如未指定自动取全局配置的 activeTimeout
* @return 对象自身
*/
public static SaLoginModel setActiveTimeout(long activeTimeout) {
return create().setActiveTimeout(activeTimeout);
}
/**
* @param extraData 扩展信息只在jwt模式下生效
* @return 登录参数 Model

View File

@ -47,10 +47,15 @@ public class SaLoginModel {
public Boolean isLastingCookie = true;
/**
* 指定此次登录token的有效期, 单位: 如未指定自动取全局配置的timeout值
* 指定此次登录 token 有效期单位 如未指定自动取全局配置的 timeout
*/
public Long timeout;
/**
* 指定此次登录 token 最低活跃频率单位如未指定则使用全局配置的 activeTimeout
*/
private Long activeTimeout;
/**
* 扩展信息只在jwt模式下生效
*/
@ -91,16 +96,6 @@ public class SaLoginModel {
return isLastingCookie;
}
/**
* @return 是否为持久Cookie临时Cookie在浏览器关闭时会自动删除持久Cookie在重新打开后依然存在
*/
public Boolean getIsLastingCookieOrFalse() {
if(isLastingCookie == null) {
return false;
}
return isLastingCookie;
}
/**
* @param isLastingCookie 是否为持久Cookie临时Cookie在浏览器关闭时会自动删除持久Cookie在重新打开后依然存在
* @return 对象自身
@ -111,24 +106,14 @@ public class SaLoginModel {
}
/**
* @return 指定此次登录token的有效期, 单位: 如未指定自动取全局配置的timeout值
* @return 指定此次登录 token 有效期单位
*/
public Long getTimeout() {
return timeout;
}
/**
* @return timeout 如果此配置项尚未配置则取全局配置的值
*/
public Long getTimeoutOrGlobalConfig() {
if(timeout == null) {
timeout = SaManager.getConfig().getTimeout();
}
return timeout;
}
/**
* @param timeout 指定此次登录token的有效期, 单位: 如未指定自动取全局配置的timeout值
* @param timeout 指定此次登录 token 有效期单位 如未指定自动取全局配置的 timeout
* @return 对象自身
*/
public SaLoginModel setTimeout(long timeout) {
@ -136,6 +121,23 @@ public class SaLoginModel {
return this;
}
/**
* @return 此次登录 token 最低活跃频率单位如未指定则使用全局配置的 activeTimeout
*/
public Long getActiveTimeout() {
return activeTimeout;
}
/**
* @param activeTimeout 指定此次登录 token 最低活跃频率单位如未指定则使用全局配置的 activeTimeout
* @return 对象自身
*/
public SaLoginModel setActiveTimeout(long activeTimeout) {
this.activeTimeout = activeTimeout;
return this;
}
/**
* @return 扩展信息只在jwt模式下生效
*/
@ -175,16 +177,6 @@ public class SaLoginModel {
return isWriteHeader;
}
/**
* @return 是否在登录后将 Token 写入到响应头 如果此配置项尚未配置则取全局配置的值
*/
public Boolean getIsWriteHeaderOrGlobalConfig() {
if(isWriteHeader == null) {
isWriteHeader = SaManager.getConfig().getIsWriteHeader();
}
return isWriteHeader;
}
/**
* @param isWriteHeader 是否在登录后将 Token 写入到响应头
* @return 对象自身
@ -213,6 +205,7 @@ public class SaLoginModel {
this.tokenSignTag = tokenSignTag;
return this;
}
/*
* toString
*/
@ -222,6 +215,7 @@ public class SaLoginModel {
+ "device=" + device
+ ", isLastingCookie=" + isLastingCookie
+ ", timeout=" + timeout
+ ", activeTimeout=" + activeTimeout
+ ", extraData=" + extraData
+ ", token=" + token
+ ", isWriteHeader=" + isWriteHeader
@ -232,6 +226,36 @@ public class SaLoginModel {
// ------ 附加方法
/**
* @return 是否为持久Cookie临时Cookie在浏览器关闭时会自动删除持久Cookie在重新打开后依然存在
*/
public Boolean getIsLastingCookieOrFalse() {
if(isLastingCookie == null) {
return false;
}
return isLastingCookie;
}
/**
* @return timeout 如果此配置项尚未配置则取全局配置的值
*/
public Long getTimeoutOrGlobalConfig() {
if(timeout == null) {
timeout = SaManager.getConfig().getTimeout();
}
return timeout;
}
/**
* @return 是否在登录后将 Token 写入到响应头 如果此配置项尚未配置则取全局配置的值
*/
public Boolean getIsWriteHeaderOrGlobalConfig() {
if(isWriteHeader == null) {
isWriteHeader = SaManager.getConfig().getIsWriteHeader();
}
return isWriteHeader;
}
/**
* 写入扩展数据只在jwt模式下生效
* @param key
@ -288,7 +312,7 @@ public class SaLoginModel {
}
return device;
}
/**
* 构建对象初始化默认值
* @return 对象自身

View File

@ -30,7 +30,7 @@ package cn.dev33.satoken.stp;
* "tokenTimeout": 2591977, // token剩余有效期 (单位: )
* "sessionTimeout": 2591977, // Account-Session剩余有效时间 (单位: )
* "tokenSessionTimeout": -2, // Token-Session剩余有效时间 (单位: ) (-2表示系统中不存在这个缓存)
* "tokenActivityTimeout": -1, // token剩余无操作有效时间 (单位: )
* "tokenActiveTimeout": -1, // Token 距离被冻结还剩多少时间 (单位: )
* "loginDevice": "default-device" // 登录设备类型
* }
* </pre>
@ -65,8 +65,8 @@ public class SaTokenInfo {
/** Token-Session 剩余有效时间(单位: 秒) */
public long tokenSessionTimeout;
/** token 剩余无操作有效时间(单位: 秒) */
public long tokenActivityTimeout;
/** token 距离被冻结还剩多少时间(单位: 秒) */
public long tokenActiveTimeout;
/** 登录设备类型 */
public String loginDevice;
@ -189,17 +189,17 @@ public class SaTokenInfo {
}
/**
* @return token 剩余无操作有效时间单位:
* @return token 距离被冻结还剩多少时间单位:
*/
public long getTokenActivityTimeout() {
return tokenActivityTimeout;
public long getTokenActiveTimeout() {
return tokenActiveTimeout;
}
/**
* @param tokenActivityTimeout token 剩余无操作有效时间单位:
* @param tokenActiveTimeout token 距离被冻结还剩多少时间单位:
*/
public void setTokenActivityTimeout(long tokenActivityTimeout) {
this.tokenActivityTimeout = tokenActivityTimeout;
public void setTokenActiveTimeout(long tokenActiveTimeout) {
this.tokenActiveTimeout = tokenActiveTimeout;
}
/**
@ -238,7 +238,7 @@ public class SaTokenInfo {
return "SaTokenInfo [tokenName=" + tokenName + ", tokenValue=" + tokenValue + ", isLogin=" + isLogin
+ ", loginId=" + loginId + ", loginType=" + loginType + ", tokenTimeout=" + tokenTimeout
+ ", sessionTimeout=" + sessionTimeout + ", tokenSessionTimeout=" + tokenSessionTimeout
+ ", tokenActivityTimeout=" + tokenActivityTimeout + ", loginDevice=" + loginDevice + ", tag=" + tag
+ ", tokenActiveTimeout=" + tokenActiveTimeout + ", loginDevice=" + loginDevice + ", tag=" + tag
+ "]";
}

View File

@ -34,6 +34,7 @@ import cn.dev33.satoken.session.TokenSign;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaTokenConsts;
import cn.dev33.satoken.util.SaValue2Box;
import java.util.ArrayList;
import java.util.Collections;
@ -342,7 +343,7 @@ public class StpLogic {
info.tokenTimeout = getTokenTimeout();
info.sessionTimeout = getSessionTimeout();
info.tokenSessionTimeout = getTokenSessionTimeout();
info.tokenActivityTimeout = getTokenActivityTimeout();
info.tokenActiveTimeout = getTokenActiveTimeout();
info.loginDevice = getLoginDevice();
return info;
}
@ -401,7 +402,7 @@ public class StpLogic {
// 1创建会话
String token = createLoginSession(id, loginModel);
// 2在当前客户端注入Token
// 2在当前客户端注入 token
setTokenValue(token, loginModel);
}
@ -445,8 +446,10 @@ public class StpLogic {
// 6保存 token -> id 的映射关系方便日后根据 token 找账号 id
saveTokenToIdMapping(tokenValue, id, loginModel.getTimeout());
// 7写入这个 token 的最后活跃时间 token-last-activity
setLastActivityToNow(tokenValue);
// 7写入这个 token 的最后活跃时间 token-last-active
if(isOpenCheckActiveTimeout()) {
setLastActiveToNow(tokenValue, loginModel.getActiveTimeout(), loginModel.getTimeoutOrGlobalConfig());
}
// 8$$ 发布全局事件账号 xxx 登录成功
SaTokenEventCenter.doLogin(loginType, id, tokenValue, loginModel);
@ -541,10 +544,15 @@ public class StpLogic {
// 如果不支持开发者却传入了 extra 扩展参数那么就打印警告信息
Map<String, Object> extraData = loginModel.getExtraData();
if(extraData != null && extraData.size() > 0) {
SaManager.log.warn("当前 StpLogic 不支持 extra 扩展参数模式,传入的 extra 将被忽略");
SaManager.log.warn("当前 StpLogic 不支持 extra 扩展参数模式,传入的 extra 数将被忽略");
}
}
// 5如果全局配置未启动动态 activeTimeout 功能但是此次登录却传入了 activeTimeout 参数那么就打印警告信息
if( ! getConfig().getDynamicActiveTimeout() && loginModel.getActiveTimeout() != null) {
SaManager.log.warn("当前全局配置未开启动态 activeTimeout 功能,传入的 activeTimeout 参数将被忽略");
}
}
// --- 注销
@ -570,7 +578,7 @@ public class StpLogic {
storage.delete(splicingKeyJustCreatedSave());
// 4清除当前上下文的 [ 活跃度校验 check 标记 ]
storage.delete(SaTokenConsts.TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY);
storage.delete(SaTokenConsts.TOKEN_ACTIVE_TIMEOUT_CHECKED_KEY);
// 5清除这个 token 的其它相关信息
logoutByTokenValue(tokenValue);
@ -606,7 +614,7 @@ public class StpLogic {
session.removeTokenSign(tokenValue);
// 2.3清除这个 token 的最后活跃时间记录
clearLastActivity(tokenValue);
clearLastActive(tokenValue);
// 2.4清除 token -> id 的映射关系
deleteTokenToIdMapping(tokenValue);
@ -654,7 +662,7 @@ public class StpLogic {
session.removeTokenSign(tokenValue);
// 3.3清除这个 token 的最后活跃时间记录
clearLastActivity(tokenValue);
clearLastActive(tokenValue);
// 3.4清除 token -> id 的映射关系
deleteTokenToIdMapping(tokenValue);
@ -677,7 +685,7 @@ public class StpLogic {
*/
public void logoutByTokenValue(String tokenValue) {
// 1清除这个 token 的最后活跃时间记录
clearLastActivity(tokenValue);
clearLastActive(tokenValue);
// 2清除这个 token Token-Session 对象
deleteTokenSession(tokenValue);
@ -736,7 +744,7 @@ public class StpLogic {
session.removeTokenSign(tokenValue);
// 2.3清除这个 token 的最后活跃时间记录
clearLastActivity(tokenValue);
clearLastActive(tokenValue);
// 2.4将此 token 标记为已被踢下线
updateTokenToIdMapping(tokenValue, NotLoginException.KICK_OUT);
@ -761,7 +769,7 @@ public class StpLogic {
*/
public void kickoutByTokenValue(String tokenValue) {
// 1清除这个 token 的最后活跃时间记录
clearLastActivity(tokenValue);
clearLastActive(tokenValue);
// 2此处不需要清除它的 Token-Session 对象
// deleteTokenSession(tokenValue);
@ -808,7 +816,7 @@ public class StpLogic {
session.removeTokenSign(tokenValue);
// 2.3清除这个 token 的最后活跃时间记录
clearLastActivity(tokenValue);
clearLastActive(tokenValue);
// 2.4将此 token 标记为已被顶下线
updateTokenToIdMapping(tokenValue, NotLoginException.BE_REPLACED);
@ -886,15 +894,15 @@ public class StpLogic {
throw NotLoginException.newInstance(loginType, KICK_OUT, KICK_OUT_MESSAGE, tokenValue).setCode(SaErrorCode.CODE_11015);
}
// 7检查此 token 的最后活跃时间是否已经超过了 activity-timeout 的限制
// 7检查此 token 的最后活跃时间是否已经超过了 active-timeout 的限制
// 如果是则代表其已被冻结需要抛出token 已过期
checkActivityTimeout(tokenValue);
checkActiveTimeout(tokenValue);
// ------ 至此loginId 已经是一个合法的值代表当前会话是一个正常的登录状态了
// 8如果配置了自动续签功能, : 更新这个 token 的最后活跃时间 注意此处的续签是在续 activity-timeout而非 timeout
if(getConfig().getAutoRenew()) {
updateLastActivityToNow(tokenValue);
// 8如果配置了自动续签功能, : 更新这个 token 的最后活跃时间 注意此处的续签是在续 active-timeout而非 timeout
if(isOpenCheckActiveTimeout() && getConfig().getAutoRenew()) {
updateLastActiveToNow(tokenValue);
}
// 9返回 loginId
@ -947,7 +955,7 @@ public class StpLogic {
}
// 4如果 token 已被冻结也返回 null
if(getTokenActivityTimeoutByToken(tokenValue) == SaTokenDao.NOT_VALUE_EXPIRE) {
if(getTokenActiveTimeoutByToken(tokenValue) == SaTokenDao.NOT_VALUE_EXPIRE) {
return null;
}
@ -1285,7 +1293,9 @@ public class StpLogic {
);
// 写入此 token 的最后活跃时间
setLastActivityToNow(tokenValue);
if(isOpenCheckActiveTimeout()) {
setLastActiveToNow(tokenValue, null, null);
}
// 在当前上下文写入此 TokenValue
setTokenValue(tokenValue);
@ -1317,38 +1327,77 @@ public class StpLogic {
}
// ------------------- Activity-Timeout token 最低活跃度 验证相关 -------------------
// ------------------- Active-Timeout token 最低活跃度 验证相关 -------------------
/**
* 写入指定 token [ 最后活跃时间 ] 为当前时间戳
* 写入指定 token [ 最后活跃时间 ] 为当前时间戳
*
* @param tokenValue 指定token
* @param tokenValue 指定token
* @param activeTimeout 这个 token 的最低活跃频率单位 null 代表使用全局配置的 activeTimeout
* @param timeout 保存数据时使用的 ttl 单位 null 代表使用全局配置的 timeout
*/
protected void setLastActivityToNow(String tokenValue) {
protected void setLastActiveToNow(String tokenValue, Long activeTimeout, Long timeout) {
// 如果提供的 token 无效或者配置没有打开 token 活跃度校验, 则立即返回无需操作
if(SaFoxUtil.isEmpty(tokenValue) || ! isOpenActivityCheck() ) {
return;
}
// 如果提供的 timeout 为null则使用全局配置的 timeout
SaTokenConfig config = getConfig();
if(timeout == null) {
timeout = config.getTimeout();
}
// activeTimeout 变量无需赋值默认值因为当缓存中没有这个值时会自动使用全局配置的值
// [ 最后活跃时间 ] 标记为当前时间戳
getSaTokenDao().set(splicingKeyLastActivityTime(tokenValue), String.valueOf(System.currentTimeMillis()), getConfig().getTimeout());
String key = splicingKeyLastActiveTime(tokenValue);
String value = String.valueOf(System.currentTimeMillis());
if(config.getDynamicActiveTimeout() && activeTimeout != null) {
value += "," + activeTimeout;
}
getSaTokenDao().set(key, value, timeout);
}
/**
/**
* 续签指定 token将这个 token [ 最后活跃时间 ] 更新为当前时间戳
*
* @param tokenValue 指定token
*/
public void updateLastActiveToNow(String tokenValue) {
// 如果提供的 token 无效或者配置没有打开 token 活跃度校验, 则立即返回无需操作
if(SaFoxUtil.isEmpty(tokenValue) || ! isOpenCheckActiveTimeout() ) {
return;
}
// 将这个 token [ 最后活跃时间 ] 更新为当前时间戳
String key = splicingKeyLastActiveTime(tokenValue);
String value = new SaValue2Box(System.currentTimeMillis(), getTokenUseActiveTimeout(tokenValue)).toString();
getSaTokenDao().update(key, value);
}
/**
* 续签当前 token( [最后操作时间] 更新为当前时间戳)
* <h2>
* 请注意: 即使 token 已被冻结 也可续签成功
* 如果此场景下需要提示续签失败可在此之前调用 checkActiveTimeout() 强制检查是否冻结即可
* </h2>
*/
public void updateLastActiveToNow() {
updateLastActiveToNow(getTokenValue());
}
/**
* 清除指定 Token [ 最后活跃时间记录 ]
*
* @param tokenValue 指定 token
*/
protected void clearLastActivity(String tokenValue) {
protected void clearLastActive(String tokenValue) {
// 如果提供的 token 无效或者配置没有打开 token 活跃度校验, 则立即返回无需操作
if(SaFoxUtil.isEmpty(tokenValue) || ! isOpenActivityCheck() ) {
if(SaFoxUtil.isEmpty(tokenValue) || ! isOpenCheckActiveTimeout() ) {
return;
}
// 删除 [ 最后活跃时间 ]
getSaTokenDao().delete(splicingKeyLastActivityTime(tokenValue));
String key = splicingKeyLastActiveTime(tokenValue);
getSaTokenDao().delete(key);
}
/**
@ -1356,73 +1405,72 @@ public class StpLogic {
*
* @param tokenValue 指定 token
*/
public void checkActivityTimeout(String tokenValue) {
public void checkActiveTimeout(String tokenValue) {
// 如果提供的 token 无效或者配置没有打开 token 活跃度校验, 则立即返回无需操作
if(SaFoxUtil.isEmpty(tokenValue) || ! isOpenActivityCheck() ) {
if(SaFoxUtil.isEmpty(tokenValue) || ! isOpenCheckActiveTimeout() ) {
return;
}
// 如果本次请求已经有了 [ 检查标记 ]说明已经校验过了此时无需重复校验立即返回
// 下面开始校验这个 token 是否已被冻结
// storage.get(key, () -> {}) 可以避免一次请求多次校验造成不必要的性能消耗
SaStorage storage = SaHolder.getStorage();
if(storage.get(SaTokenConsts.TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY) != null) {
return;
}
storage.get(SaTokenConsts.TOKEN_ACTIVE_TIMEOUT_CHECKED_KEY, () -> {
// ------------ 下面开始校验这个 token 是否已被冻结
// 1获取这个 token 的剩余活跃有效期
long activeTimeout = getTokenActiveTimeoutByToken(tokenValue);
// 1获取这个 token 的剩余活跃有效期
long timeout = getTokenActivityTimeoutByToken(tokenValue);
// 2值为 -1 代表此 token 已经被设置永不冻结无须继续验证
if(activeTimeout == SaTokenDao.NEVER_EXPIRE) {
return true;
}
// 2值为 -1 代表此 token 已经被设置永不冻结无须继续验证
if(timeout == SaTokenDao.NEVER_EXPIRE) {
// 此句代码含义参考最下面
storage.set(SaTokenConsts.TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY, true);
return;
}
// 3值为 -2 代表已被冻结此时需要抛出异常
if(activeTimeout == SaTokenDao.NOT_VALUE_EXPIRE) {
throw NotLoginException.newInstance(loginType, TOKEN_FREEZE, TOKEN_FREEZE_MESSAGE, tokenValue).setCode(SaErrorCode.CODE_11016);
}
// 3值为 -2 代表已被冻结此时需要抛出异常
if(timeout == SaTokenDao.NOT_VALUE_EXPIRE) {
throw NotLoginException.newInstance(loginType, TOKEN_FREEZE, TOKEN_FREEZE_MESSAGE, tokenValue).setCode(SaErrorCode.CODE_11016);
}
// --- 至此验证已通过
// 4打上 [ 检查标记 ]标记一下当前请求已经通过校验避免一次请求多次校验造成不必要的性能消耗
storage.set(SaTokenConsts.TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY, true);
// --- 验证通过
return true;
});
}
/**
* 检查当前 token 是否已被冻结如果是则抛出异常
*/
public void checkActivityTimeout() {
checkActivityTimeout(getTokenValue());
public void checkActiveTimeout() {
checkActiveTimeout(getTokenValue());
}
/**
* 续签指定 token将这个 token [ 最后活跃时间 ] 更新为当前时间戳
/**
* 获取指定 token 在缓存中的 activeTimeout 如果不存在则返回 null
*
* @param tokenValue 指定token
*/
public void updateLastActivityToNow(String tokenValue) {
// 如果提供的 token 无效或者配置没有打开 token 活跃度校验, 则立即返回无需操作
if(SaFoxUtil.isEmpty(tokenValue) || ! isOpenActivityCheck() ) {
return;
* @param tokenValue 指定token
* @return /
*/
public Long getTokenUseActiveTimeout(String tokenValue) {
// 先取出这个 token 的最后活跃时间值
String key = splicingKeyLastActiveTime(tokenValue);
String value = getSaTokenDao().get(key);
// 先获取缓存库里的值获取不到则使用全局配置
SaValue2Box box = new SaValue2Box(value);
return box.getValue2AsLong(null);
}
/**
* 获取指定 token 在缓存中的 activeTimeout 如果不存在则返回全局配置的 activeTimeout
*
* @param tokenValue 指定token
* @return /
*/
public long getTokenUseActiveTimeoutOrGlobalConfig(String tokenValue) {
Long activeTimeout = getTokenUseActiveTimeout(tokenValue);
if(activeTimeout == null) {
return getConfig().getActiveTimeout();
}
// 将这个 token [ 最后活跃时间 ] 更新为当前时间戳
getSaTokenDao().update(splicingKeyLastActivityTime(tokenValue), String.valueOf(System.currentTimeMillis()));
}
/**
* 续签当前 token( [最后操作时间] 更新为当前时间戳)
* <h2>
* 请注意: 即使 token 已被冻结 也可续签成功
* 如果此场景下需要提示续签失败可在此之前调用 checkActivityTimeout() 强制检查是否冻结即可
* </h2>
*/
public void updateLastActivityToNow() {
updateLastActivityToNow(getTokenValue());
}
return activeTimeout;
}
// ------------------- 过期时间相关 -------------------
@ -1499,8 +1547,8 @@ public class StpLogic {
*
* @return /
*/
public long getTokenActivityTimeout() {
return getTokenActivityTimeoutByToken(getTokenValue());
public long getTokenActiveTimeout() {
return getTokenActiveTimeoutByToken(getTokenValue());
}
/**
@ -1509,10 +1557,10 @@ public class StpLogic {
* @param tokenValue 指定 token
* @return /
*/
public long getTokenActivityTimeoutByToken(String tokenValue) {
public long getTokenActiveTimeoutByToken(String tokenValue) {
// 如果全局配置了永不冻结, 则返回 -1
if( ! isOpenActivityCheck() ) {
if( ! isOpenCheckActiveTimeout() ) {
return SaTokenDao.NEVER_EXPIRE;
}
@ -1524,27 +1572,32 @@ public class StpLogic {
// ------ 开始查询
// 1先获取这个 token 的最后活跃时间13位时间戳
String keyLastActivityTime = splicingKeyLastActivityTime(tokenValue);
String lastActivityTimeString = getSaTokenDao().get(keyLastActivityTime);
String key = splicingKeyLastActiveTime(tokenValue);
String lastActiveTimeString = getSaTokenDao().get(key);
// 2如果查不到返回-2
if(lastActivityTimeString == null) {
if(lastActiveTimeString == null) {
return SaTokenDao.NOT_VALUE_EXPIRE;
}
// 3计算最后活跃时间 此时此刻 的时间差
// 3计算最后活跃时间 距离 此时此刻 的时间差
// 计算公式为: (当前时间 - 最后活跃时间) / 1000
long lastActivityTime = Long.parseLong(lastActivityTimeString);
long apartSecond = (System.currentTimeMillis() - lastActivityTime) / 1000;
SaValue2Box box = new SaValue2Box(lastActiveTimeString);
long lastActiveTime = box.getValue1AsLong();
// 实际时间差
long timeDiff = (System.currentTimeMillis() - lastActiveTime) / 1000;
// token 允许的时间差
long allowTimeDiff = getTokenUseActiveTimeoutOrGlobalConfig(tokenValue);
// 4校验这个时间差是否超过了允许的值
// 计算公式为: 允许的最大时间差 - 实际时间差判断是否 < 0 如果是则代表已经被冻结 返回-2
long timeout = getConfig().getActivityTimeout() - apartSecond;
if(timeout < 0) {
long activeTimeout = allowTimeDiff - timeDiff;
if(activeTimeout < 0) {
return SaTokenDao.NOT_VALUE_EXPIRE;
} else {
// 否则代表没冻结返回剩余有效时间
return timeout;
return activeTimeout;
}
}
@ -1597,8 +1650,8 @@ public class StpLogic {
getSessionByLoginId(loginId).updateMinTimeout(timeout);
// 5更新此 token 的最后活跃时间
if(isOpenActivityCheck()) {
dao.updateTimeout(splicingKeyLastActivityTime(tokenValue), timeout);
if(isOpenCheckActiveTimeout()) {
dao.updateTimeout(splicingKeyLastActiveTime(tokenValue), timeout);
}
// 6$$ 发布事件某某 token 被续期了
@ -2603,8 +2656,8 @@ public class StpLogic {
* @param tokenValue token值
* @return key
*/
public String splicingKeyLastActivityTime(String tokenValue) {
return getConfig().getTokenName() + ":" + loginType + ":last-activity:" + tokenValue;
public String splicingKeyLastActiveTime(String tokenValue) {
return getConfig().getTokenName() + ":" + loginType + ":last-active:" + tokenValue;
}
/**
@ -2677,8 +2730,8 @@ public class StpLogic {
*
* @return /
*/
public boolean isOpenActivityCheck() {
return getConfig().getActivityTimeout() != SaTokenDao.NEVER_EXPIRE;
public boolean isOpenCheckActiveTimeout() {
return getConfig().getActiveTimeout() != SaTokenDao.NEVER_EXPIRE;
}
/**

View File

@ -26,7 +26,7 @@ import java.util.List;
* Sa-Token 权限认证工具类
*
* @author click33
* @since 1.10.0
* @since 1.0.0
*/
public class StpUtil {
@ -493,26 +493,26 @@ public class StpUtil {
}
// ------------------- Activity-Timeout token 最低活跃度 验证相关 -------------------
/**
* 检查当前 token 是否已被冻结如果是则抛出异常
*/
public static void checkActivityTimeout() {
stpLogic.checkActivityTimeout();
}
// ------------------- Active-Timeout token 最低活跃度 验证相关 -------------------
/**
* 续签当前 token( [最后操作时间] 更新为当前时间戳)
* <h2>
* 请注意: 即使 token 已被冻结 也可续签成功
* 如果此场景下需要提示续签失败可在此之前调用 checkActivityTimeout() 强制检查是否冻结即可
* 如果此场景下需要提示续签失败可在此之前调用 checkActiveTimeout() 强制检查是否冻结即可
* </h2>
*/
public static void updateLastActivityToNow() {
stpLogic.updateLastActivityToNow();
public static void updateLastActiveToNow() {
stpLogic.updateLastActiveToNow();
}
/**
* 检查当前 token 是否已被冻结如果是则抛出异常
*/
public static void checkActiveTimeout() {
stpLogic.checkActiveTimeout();
}
// ------------------- 过期时间相关 -------------------
@ -558,8 +558,8 @@ public class StpUtil {
*
* @return /
*/
public static long getTokenActivityTimeout() {
return stpLogic.getTokenActivityTimeout();
public static long getTokenActiveTimeout() {
return stpLogic.getTokenActiveTimeout();
}
/**

View File

@ -67,9 +67,9 @@ public class SaTokenConsts {
public static final String JUST_CREATED_NOT_PREFIX = "JUST_CREATED_NOT_PREFIX_";
/**
* 常量 key 标记: 如果本次请求已经验证过 [ 临时过期 ] , 则以此值存储在当前 request
* 常量 key 标记: 如果本次请求已经验证过 activeTimeout, 则以此 key storage 中做一个标记
*/
public static final String TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY = "TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY_";
public static final String TOKEN_ACTIVE_TIMEOUT_CHECKED_KEY = "TOKEN_ACTIVE_TIMEOUT_CHECKED_KEY_";
/**
* 常量 key 标记: 在登录时默认使用的设备类型
@ -193,6 +193,13 @@ public class SaTokenConsts {
* 请更换为 JUST_CREATED
*/
@Deprecated
public static final String JUST_CREATED_SAVE_KEY = JUST_CREATED;
public static final String JUST_CREATED_SAVE_KEY = JUST_CREATED;
/**
* 请更换为 TOKEN_ACTIVE_TIMEOUT_CHECKED_KEY
*/
@Deprecated
public static final String TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY = TOKEN_ACTIVE_TIMEOUT_CHECKED_KEY;
}

View File

@ -0,0 +1,219 @@
/*
* Copyright 2020-2099 sa-token.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.util;
/**
* 封装两个值的容器方便取值写值等操作value1 value2 用逗号隔开形如123,abc
*
* @author click33
* @since 1.35.0
*/
public class SaValue2Box {
/**
* 第一个值
*/
private Object value1;
/**
* 第二个值
*/
private Object value2;
/**
* 直接提供两个值构建
* @param value1 第一个值
* @param value2 第二个值
*/
public SaValue2Box(Object value1, Object value2) {
this.value1 = value1;
this.value2 = value2;
}
/**
* 根据字符串构建字符串形如123,abc
* @param valueString 形如123,abc
*/
public SaValue2Box(String valueString) {
if(valueString == null){
return;
}
String[] split = valueString.split(",");
if(split.length == 0){
// do nothing
}
else if(split.length == 1){
this.value1 = split[0];
}
else {
this.value1 = split[0];
this.value2 = split[1];
}
}
/**
* 获取第一个值
* @return 第一个值
*/
public Object getValue1() {
return value1;
}
/**
* 获取第二个值
* @return 第二个值
*/
public Object getValue2() {
return value2;
}
/**
* 设置第一个值
* @param value1 第一个值
*/
public void setValue1(Object value1) {
this.value1 = value1;
}
/**
* 设置第二个值
* @param value2 第二个值
*/
public void setValue2(Object value2) {
this.value2 = value2;
}
/**
* 判断第一个值是否为 null 或者空字符串
* @return /
*/
public boolean value1IsEmpty() {
return SaFoxUtil.isEmpty(value1);
}
/**
* 判断第二个值是否为 null 或者空字符串
* @return /
*/
public boolean value2IsEmpty() {
return SaFoxUtil.isEmpty(value2);
}
/**
* 获取第一个值并转化为 String 类型
* @return /
*/
public String getValue1AsString() {
return value1 == null ? null : value1.toString();
}
/**
* 获取第二个值并转化为 String 类型
* @return /
*/
public String getValue2AsString() {
return value2 == null ? null : value2.toString();
}
/**
* 获取第一个值并转化为 long 类型
* @return /
*/
public long getValue1AsLong() {
return Long.parseLong(value1.toString());
}
/**
* 获取第二个值并转化为 long 类型
* @return /
*/
public long getValue2AsLong() {
return Long.parseLong(value2.toString());
}
/**
* 获取第一个值并转化为 long 类型值不存在则返回默认值
* @return /
*/
public Long getValue1AsLong(Long defaultValue) {
// 这里如果改成三元表达式会导致自动拆箱造成空指针异常所以只能用 if-else
if(value1 == null){
return defaultValue;
}
return Long.parseLong(value1.toString());
}
/**
* 获取第二个值并转化为 long 类型值不存在则返回默认值
* @return /
*/
public Long getValue2AsLong(Long defaultValue) {
// 这里如果改成三元表达式会导致自动拆箱造成空指针异常所以只能用 if-else
if(value2 == null){
return defaultValue;
}
return Long.parseLong(value2.toString());
}
/**
* 该容器是否为无值状态value1 无值value2 无值
* @return /
*/
public boolean isNotValueState() {
return value1IsEmpty() && value2IsEmpty();
}
/**
* 该容器是否为单值状态value1 有值value2 == 无值
* @return /
*/
public boolean isSingleValueState() {
return ! value1IsEmpty() && value2IsEmpty();
}
/**
* 该容器是否为双值状态value2 有值 value2 有值的情况下即使 value1 无值也视为双值状态
* @return /
*/
public boolean isDoubleValueState() {
return ! value2IsEmpty();
}
/**
* 获取两个值的字符串形式形如123,abc
*
* <br><br>
* <pre>
* System.out.println(new SaValue2Box(1, 2)); // 1,2
* System.out.println(new SaValue2Box(null, null)); // null
* System.out.println(new SaValue2Box(1, null)); // 1
* System.out.println(new SaValue2Box(null, 2)); // 2
* </pre>
* @return /
*/
@Override
public String toString() {
if(value1 == null && value2 == null) {
return null;
}
if(value1 != null && value2 == null) {
return value1.toString();
}
return (value1 == null ? "" : value1.toString()) + "," + (value2 == null ? "" : value2.toString());
}
}

View File

@ -111,7 +111,7 @@ public class LoginAuthController {
System.out.println("当前登录账号的类型:" + info.getLoginType());
System.out.println("当前登录客户端的设备类型:" + info.getLoginDevice());
System.out.println("当前 Token 的剩余有效期:" + info.getTokenTimeout()); // 单位-1代表永久有效-2代表值不存在
System.out.println("当前 Token 的剩余临时有效期:" + info.getTokenActivityTimeout()); // 单位-1代表永久有效-2代表值不存在
System.out.println("当前 Token 距离被冻结还剩:" + info.getTokenActiveTimeout()); // 单位-1代表永久有效-2代表值不存在
System.out.println("当前 Account-Session 的剩余有效期" + info.getSessionTimeout()); // 单位-1代表永久有效-2代表值不存在
System.out.println("当前 Token-Session 的剩余有效期" + info.getTokenSessionTimeout()); // 单位-1代表永久有效-2代表值不存在

View File

@ -7,17 +7,15 @@ import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpLogic;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* Sa-Token 权限认证工具类 (User)
* Sa-Token 权限认证工具类 (User )
*
* @author click33
* @since <= 1.34.0
* @since 1.0.0
*/
@Component
public class StpUserUtil {
private StpUserUtil() {}
@ -25,7 +23,7 @@ public class StpUserUtil {
/**
* 多账号体系下的类型标识
*/
public static final String TYPE = "user";
public static final String TYPE = "login";
/**
* 底层使用的 StpLogic 对象
@ -483,24 +481,24 @@ public class StpUserUtil {
}
// ------------------- Activity-Timeout token 最低活跃度 验证相关 -------------------
/**
* 检查当前 token 是否已被冻结如果是则抛出异常
*/
public static void checkActivityTimeout() {
stpLogic.checkActivityTimeout();
}
// ------------------- Active-Timeout token 最低活跃度 验证相关 -------------------
/**
* 续签当前 token( [最后操作时间] 更新为当前时间戳)
* <h2>
* 请注意: 即使 token 已被冻结 也可续签成功
* 如果此场景下需要提示续签失败可在此之前调用 checkActivityTimeout() 强制检查是否冻结即可
* 如果此场景下需要提示续签失败可在此之前调用 checkActiveTimeout() 强制检查是否冻结即可
* </h2>
*/
public static void updateLastActivityToNow() {
stpLogic.updateLastActivityToNow();
public static void updateLastActiveToNow() {
stpLogic.updateLastActiveToNow();
}
/**
* 检查当前 token 是否已被冻结如果是则抛出异常
*/
public static void checkActiveTimeout() {
stpLogic.checkActiveTimeout();
}
@ -548,8 +546,8 @@ public class StpUserUtil {
*
* @return /
*/
public static long getTokenActivityTimeout() {
return stpLogic.getTokenActivityTimeout();
public static long getTokenActiveTimeout() {
return stpLogic.getTokenActiveTimeout();
}
/**

View File

@ -2,22 +2,22 @@
server:
port: 8081
# sa-token配置
# sa-token 配置
sa-token:
# token名称 (同时也是cookie名称)
# token 名称 (同时也是 cookie 名称)
token-name: satoken
# token有效期单位s 默认30天, -1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: false
is-log: true
spring:
# redis配置

View File

@ -2,21 +2,21 @@
server:
port: 8081
# sa-token配置
# sa-token 配置
sa-token:
# token名称 (同时也是cookie名称)
# token 名称 (同时也是 cookie 名称)
token-name: satoken
# token有效期单位s 默认30天, -1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否打印操作日志
# 是否输出操作日志
is-log: true
# jwt秘钥
jwt-secret-key: asdasdasifhueuiwyurfewbfjsdafjk

View File

@ -2,24 +2,22 @@
server:
port: 80
# sa-token配置
# sa-token 配置
sa-token:
# token名称 (同时也是cookie名称)
# token 名称 (同时也是 cookie 名称)
token-name: satoken
# token有效期单位s 默认30天, -1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 禁止写入cookie
is-read-cookie: false
# 在多人登录同一账号时是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: false
# token风格
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: false
is-log: true
spring:
# redis配置

View File

@ -159,8 +159,8 @@ public class TestController {
public AjaxJson atCheck() {
System.out.println("======================= 进入方法,测试注解鉴权接口 ========================= ");
System.out.println("只有通过注解鉴权,才能进入此方法");
// StpUtil.checkActivityTimeout();
// StpUtil.updateLastActivityToNow();
// StpUtil.checkActiveTimeout();
// StpUtil.updateLastActiveToNow();
return AjaxJson.getSuccess();
}
@ -174,8 +174,8 @@ public class TestController {
// [活动时间] 续签 http://localhost:8081/test/rene
@Mapping("rene")
public AjaxJson rene() {
StpUtil.checkActivityTimeout();
StpUtil.updateLastActivityToNow();
StpUtil.checkActiveTimeout();
StpUtil.updateLastActiveToNow();
return AjaxJson.getSuccess("续签成功");
}

View File

@ -2,19 +2,19 @@
server:
port: 8081
# sa-token配置
# sa-token 配置
sa-token:
# token名称 (同时也是cookie名称)
# token 名称 (同时也是 cookie 名称)
token-name: satoken
# token有效期单位s 默认30天, -1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
allow-concurrent-login: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: true

View File

@ -1,20 +1,20 @@
# 端口
server:
port: 8081
# sa-token配置
# sa-token 配置
sa-token:
# token名称 (同时也是cookie名称)
# token 名称 (同时也是 cookie 名称)
token-name: satoken
# token有效期单位s 默认30天, -1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: true

View File

@ -2,21 +2,21 @@
server:
port: 8081
# sa-token配置
sa-token:
# token名称 (同时也是cookie名称)
# sa-token 配置
sa-token:
# token 名称 (同时也是 cookie 名称)
token-name: satoken
# token有效期单位s 默认30天, -1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
# 是否输出操作日志
is-log: true
spring:

View File

@ -160,8 +160,8 @@ public class TestController {
public AjaxJson atCheck() {
System.out.println("======================= 进入方法,测试注解鉴权接口 ========================= ");
System.out.println("只有通过注解鉴权,才能进入此方法");
// StpUtil.checkActivityTimeout();
// StpUtil.updateLastActivityToNow();
// StpUtil.checkActiveTimeout();
// StpUtil.updateLastActiveToNow();
return AjaxJson.getSuccess();
}
@ -175,8 +175,8 @@ public class TestController {
// [活动时间] 续签 http://localhost:8081/test/rene
@RequestMapping("rene")
public AjaxJson rene() {
StpUtil.checkActivityTimeout();
StpUtil.updateLastActivityToNow();
StpUtil.checkActiveTimeout();
StpUtil.updateLastActiveToNow();
return AjaxJson.getSuccess("续签成功");
}

View File

@ -1,23 +1,23 @@
# 端口
server:
port: 8081
# sa-token配置
# sa-token 配置
sa-token:
# token名称 (同时也是cookie名称)
# token 名称 (同时也是 cookie 名称)
token-name: satoken
# token有效期单位s 默认30天, -1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: false
is-log: true
spring:
# redis配置

View File

@ -1,20 +1,20 @@
# 端口
server:
port: 8081
# sa-token配置
# sa-token 配置
sa-token:
# token名称 (同时也是cookie名称)
# token 名称 (同时也是 cookie 名称)
token-name: satoken
# token有效期单位s 默认30天, -1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: true

View File

@ -7,17 +7,15 @@ import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpLogic;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* Sa-Token 权限认证工具类 (User)
* Sa-Token 权限认证工具类 (User )
*
* @author click33
* @since <= 1.34.0
* @since 1.0.0
*/
@Component
public class StpUserUtil {
private StpUserUtil() {}
@ -25,7 +23,7 @@ public class StpUserUtil {
/**
* 多账号体系下的类型标识
*/
public static final String TYPE = "user";
public static final String TYPE = "login";
/**
* 底层使用的 StpLogic 对象
@ -483,24 +481,24 @@ public class StpUserUtil {
}
// ------------------- Activity-Timeout token 最低活跃度 验证相关 -------------------
/**
* 检查当前 token 是否已被冻结如果是则抛出异常
*/
public static void checkActivityTimeout() {
stpLogic.checkActivityTimeout();
}
// ------------------- Active-Timeout token 最低活跃度 验证相关 -------------------
/**
* 续签当前 token( [最后操作时间] 更新为当前时间戳)
* <h2>
* 请注意: 即使 token 已被冻结 也可续签成功
* 如果此场景下需要提示续签失败可在此之前调用 checkActivityTimeout() 强制检查是否冻结即可
* 如果此场景下需要提示续签失败可在此之前调用 checkActiveTimeout() 强制检查是否冻结即可
* </h2>
*/
public static void updateLastActivityToNow() {
stpLogic.updateLastActivityToNow();
public static void updateLastActiveToNow() {
stpLogic.updateLastActiveToNow();
}
/**
* 检查当前 token 是否已被冻结如果是则抛出异常
*/
public static void checkActiveTimeout() {
stpLogic.checkActiveTimeout();
}
@ -548,8 +546,8 @@ public class StpUserUtil {
*
* @return /
*/
public static long getTokenActivityTimeout() {
return stpLogic.getTokenActivityTimeout();
public static long getTokenActiveTimeout() {
return stpLogic.getTokenActiveTimeout();
}
/**

View File

@ -1,11 +1,15 @@
package com.pj.test;
import cn.dev33.satoken.stp.SaLoginConfig;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
* 测试专用Controller
* @author click33
@ -18,14 +22,15 @@ public class TestController {
// 测试登录 ---- http://localhost:8081/test/login
@RequestMapping("login")
public SaResult login(@RequestParam(defaultValue = "10001") long id) {
StpUtil.login(id);
StpUtil.login(id, SaLoginConfig.setActiveTimeout(20));
return SaResult.ok("登录成功");
}
// 测试 浏览器访问 http://localhost:8081/test/test
@RequestMapping("test")
public SaResult test() {
System.out.println("------------进来了");
System.out.println("------------进来了 " + SaFoxUtil.formatDate(new Date()));
StpUtil.checkLogin();
// 返回
return SaResult.data(null);
}

View File

@ -4,17 +4,17 @@ server:
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
sa-token:
# token名称 (同时也是cookie名称)
# token 名称 (同时也是 cookie 名称)
token-name: satoken
# token有效期单位s 默认30天, -1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: 100000
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: true

View File

@ -2,21 +2,21 @@
server:
port: 8081
# sa-token配置
# sa-token 配置
sa-token:
# token名称 (同时也是cookie名称)
# token 名称 (同时也是 cookie 名称)
token-name: satoken
# token有效期单位s 默认30天, -1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 日志
# 是否输出操作日志
is-log: true
spring:

View File

@ -2,21 +2,21 @@
server:
port: 8081
# sa-token配置
# sa-token 配置
sa-token:
# token名称 (同时也是cookie名称)
# token 名称 (同时也是 cookie 名称)
token-name: satoken
# token有效期单位s 默认30天, -1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 日志
# 是否输出操作日志
is-log: true
spring:

View File

@ -1,23 +1,23 @@
# 端口
server:
port: 8081
# sa-token配置
# sa-token 配置
sa-token:
# token名称 (同时也是cookie名称)
# token 名称 (同时也是 cookie 名称)
token-name: satoken
# token有效期单位s 默认30天, -1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: false
is-log: true
spring:
# redis配置

View File

@ -1,23 +1,23 @@
# 端口
server:
port: 8081
# sa-token配置
# sa-token 配置
sa-token:
# token名称 (同时也是cookie名称)
# token 名称 (同时也是 cookie 名称)
token-name: satoken
# token有效期单位s 默认30天, -1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: false
is-log: true
spring:
# redis配置

View File

@ -90,12 +90,12 @@ StpUtil.getSessionBySessionId("xxxx-xxxx-xxxx"); // 获取指定key的Session,
### 6、Token有效期相关
``` java
// 临时有效期
StpUtil.getTokenActivityTimeout(); // 获取当前 token [临时过期] 剩余有效时间 (单位: 秒)
StpUtil.checkActivityTimeout(); // 检查当前token 是否已经[临时过期],如果已经过期则抛出异常
StpUtil.updateLastActivityToNow(); // 续签当前token(将 [最后操作时间] 更新为当前时间戳)
// Token 最低活跃频率
StpUtil.getTokenActiveTimeout(); // 获取当前 token 距离被冻结还剩多少时间 (单位: 秒)
StpUtil.checkActiveTimeout(); // 检查当前token 是否已经被冻结,如果是则抛出异常
StpUtil.updateLastActiveToNow(); // 续签当前token(将 [最后操作时间] 更新为当前时间戳)
// 长久有效期
// Token 有效期
StpUtil.getTokenTimeout(); // 获取当前登录者的 token 剩余有效时间 (单位: 秒)
StpUtil.getSessionTimeout(); // 获取当前登录者的 Account-Session 剩余有效时间 (单位: 秒)
StpUtil.getTokenSessionTimeout(); // 获取当前 Token-Session 剩余有效时间 (单位: 秒)

View File

@ -79,7 +79,7 @@ SaToken 中的所有异常都是继承于 `SaTokenException` 的,也就是说
| 11013 | Token已过期 |
| 11014 | Token已被顶下线 |
| 11015 | Token已被踢下线 |
| 11016 | Token已临时过期 |
| 11016 | Token已被冻结 |
| 11031 | 在未集成 sa-token-jwt 插件时调用 getExtra() 抛出异常 |
| 11041 | 缺少指定的角色 |
| 11051 | 缺少指定的权限 |

View File

@ -15,7 +15,7 @@ token信息Model: 用来描述一个token的常用参数
"tokenTimeout": 2591977, // token剩余有效期 (单位: 秒)
"sessionTimeout": 2591977, // Account-Session剩余有效时间 (单位: 秒)
"tokenSessionTimeout": -2, // Token-Session剩余有效时间 (单位: 秒) (-2表示系统中不存在这个缓存)
"tokenActivityTimeout": -1, // token剩余无操作有效时间 (单位: 秒)
"tokenActiveTimeout": -1, // token 距离被冻结还剩的时间 (单位: 秒)
"loginDevice": "default-device" // 登录设备类型
},
}

View File

@ -2,7 +2,7 @@
<!-- 本篇介绍Token有效期的详细用法 -->
Sa-Token 提供两种 Token 自动过期策略,分别是 `timeout``activity-timeout`,配置方法如下:
Sa-Token 提供两种 Token 自动过期策略,分别是 `timeout``active-timeout`,配置方法如下:
<!---------------------------- tabs:start ---------------------------->
<!------------- tab:yaml 风格 ------------->
@ -11,14 +11,14 @@ sa-token:
# token 有效期单位默认30天-1代表永不过期
timeout: 2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
activity-timeout: -1
active-timeout: -1
```
<!------------- tab:properties 风格 ------------->
``` properties
# token 有效期单位默认30天-1代表永不过期
sa-token.timeout=2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
sa-token.activity-timeout=-1
sa-token.active-timeout=-1
```
<!---------------------------- tabs:end ---------------------------->
@ -29,7 +29,7 @@ sa-token.activity-timeout=-1
> 2. 银行为你颁发一张储蓄卡系统为你颁发一个Token以后每次存取钱都要带上这张卡后续每次访问系统都要提交 Token
> 3. 银行为这张卡设定两个过期时间:
> - 第一个是 `timeout`,代表这张卡的长久有效期,就是指这张卡最长能用多久,假设 `timeout=3年`那么3年后此卡将被银行删除想要继续来银行办理业务必须重新办卡Token 过期后想要访问系统必须重新登录)。
> - 第二个就是 `activity-timeout`,代表这张卡的最低活跃频率限制,就是指这张卡必须每隔多久来银行一次,假设 `activity-timeout=1月` 你如果超过1月不来办一次业务银行就将你的卡冻结列为长期不动户Token 长期不访问系统,被冻结,但不会被删除)。
> - 第二个就是 `active-timeout`,代表这张卡的最低活跃频率限制,就是指这张卡必须每隔多久来银行一次,假设 `active-timeout=1月` 你如果超过1月不来办一次业务银行就将你的卡冻结列为长期不动户Token 长期不访问系统,被冻结,但不会被删除)。
> 4. 两个过期策略可以单独配置也可以同时配置只要有其中一个有效期超出了范围这张卡就会变得不可用两个有效期只要有一个过期了Token就无法成功访问系统了
下面是对两个过期策略的详细解释:
@ -40,33 +40,33 @@ sa-token.activity-timeout=-1
3. `timeout`的值配置为-1后代表永久有效不会过期。
### activity-timeout
1. `activity-timeout`代表最低活跃频率,单位/秒,例如将其配置为 1800 (30分钟)代表用户如果30分钟无操作则此Token会立即过期被冻结但不会删除掉
### active-timeout
1. `active-timeout`代表最低活跃频率,单位/秒,例如将其配置为 1800 (30分钟)代表用户如果30分钟无操作则此Token会立即过期被冻结但不会删除掉
2. 如果在30分钟内用户有操作则会再次续签30分钟用户如果一直操作则会一直续签直到连续30分钟无操作Token才会过期。
3. `activity-timeout`的值配置为-1后代表永久有效不会过期此时也无需频繁续签。
3. `active-timeout`的值配置为-1后代表永久有效不会过期此时也无需频繁续签。
### 关于activity-timeout的续签
如果`activity-timeout`配置了大于零的值Sa-Token 会在登录时开始计时,在每次直接或间接调用`getLoginId()`时进行一次冻结检查与续签操作。
### 关于active-timeout的续签
如果`active-timeout`配置了大于零的值Sa-Token 会在登录时开始计时,在每次直接或间接调用`getLoginId()`时进行一次冻结检查与续签操作。
此时会有两种情况:
1. 一种是会话无操作时间太长Token已经被冻结此时框架会抛出`NotLoginException`异常(场景值=-3)
2. 另一种则是会话在`activity-timeout`有效期内通过检查此时Token可以成功续签
2. 另一种则是会话在`active-timeout`有效期内通过检查此时Token可以成功续签
### 我可以手动续签 activity-timeout 吗?
### 我可以手动续签 active-timeout 吗?
**可以!**
如果框架的自动续签算法无法满足您的业务需求你可以进行手动续签Sa-Token 提供两个API供你操作
1. `StpUtil.checkActivityTimeout()`: 检查当前Token 是否已经被冻结,如果是则抛出异常
2. `StpUtil.updateLastActivityToNow()`: 续签当前Token(将 [最后操作时间] 更新为当前时间戳)
1. `StpUtil.checkActiveTimeout()`: 检查当前Token 是否已经被冻结,如果是则抛出异常
2. `StpUtil.updateLastActiveToNow()`: 续签当前Token(将 [最后操作时间] 更新为当前时间戳)
注意:在手动续签时,即使 Token 已经被冻结也可续签成功解冻如果此场景下需要提示续签失败可采用先检查再续签的形式保证Token有效性
例如以下代码:
``` java
// 先检查是否已被冻结
StpUtil.checkActivityTimeout();
StpUtil.checkActiveTimeout();
// 检查通过后继续续签
StpUtil.updateLastActivityToNow();
StpUtil.updateLastActiveToNow();
```
同时,你还可以关闭框架的自动续签(在配置文件中配置 `autoRenew=false` ),此时续签操作完全由开发者控制,框架不再自动进行任何续签操作
@ -75,16 +75,16 @@ StpUtil.updateLastActivityToNow();
``` java
// 为指定 Token 续签
StpUtil.stpLogic.updateLastActivityToNow(tokenValue);
StpUtil.stpLogic.updateLastActiveToNow(tokenValue);
```
### timeout 与 activity-timeout 可以同时使用吗?
### timeout 与 active-timeout 可以同时使用吗?
**可以同时使用!**
两者的认证逻辑彼此独立,互不干扰,可以同时使用。
### StpUtil 类中哪些公开方法支持临时有效期自动续签 activity-timeout?
### StpUtil 类中哪些公开方法支持自动续签 active-timeout?
> 直接或间接获取了当前用户id的方法 (间接调用过 StpLogic.getLoginId() 方法)
| 包括但不限于这些: |

View File

@ -73,18 +73,20 @@ SaFoxUtil.toList(... strs); // String 数组转集合
1、首先在项目根目录创建一个配置文件`sa-token.properties`
``` java
# token名称 (同时也是cookie名称)
``` properties
# token 名称 (同时也是 cookie 名称)
tokenName=satoken
# token有效期单位s 默认30天, -1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout=2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activityTimeout=-1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) =-1
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
activeTimeout=-1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
isConcurrent=true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
isShare=true
# token风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
tokenStyle=uuid
# 是否输出操作日志
isLog=false
```

View File

@ -88,7 +88,7 @@ Sa-Token 的部分 API 只能在 Web 上下文中才能调用,例如:`StpUti
- 可能9可能是多账号鉴权的关系在多账号模式下如果是 `StpUserUtil.login()` 颁发的token你从 `StpUtil.checkLogin()` 进行校验永远都是无效token因为账号体系没对上。
**如果是Token已过期6ad93254-b286-4ec9-9997-4430b0341ca0**
- 可能1前端提交的 token 临时过期activity-timeout超时了比如配置了 activity-timeout=120但是超过了120秒没有访问接口
- 可能1前端提交的 token 已被冻结active-timeout超时了比如配置了 active-timeout=120但是超过了120秒没有访问接口
- 可能2集成jwt而且使用的是 Mixin 或 Stateless 模式而且token过期了timeout超时了
**如果是Token已被顶下线6ad93254-b286-4ec9-9997-4430b0341ca0**

View File

@ -18,7 +18,7 @@ Sa-Token 无意发明任何晦涩概念提升逼格,但在处理 issue 、Q群
#### 两种过期时间:
- timeout会话 Token 的长久有效期。
- activity-timeout会话的临时有效期
- active-timeout会话 Token 的最低活跃频率
两者的差别详见:[Token有效期详解](/fun/token-timeout)

View File

@ -150,7 +150,7 @@ eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbklkIjoiMTAwMDEiLCJybiI6IjZYYzgySzB
| 角色认证 | 支持 | 支持 | 支持 |
| 权限认证 | 支持 | 支持 | 支持 |
| timeout 有效期 | 支持 | 支持 | 支持 |
| activity-timeout 有效期 | 支持 | 支持 | 不支持 |
| active-timeout 有效期 | 支持 | 支持 | 不支持 |
| id反查Token | 支持 | 支持 | 不支持 |
| 会话管理 | 支持 | 部分支持 | 不支持 |
| 注解鉴权 | 支持 | 支持 | 支持 |

View File

@ -57,18 +57,18 @@ server:
sa-token:
# token 名称(同时也是 cookie 名称)
token-name: satoken
# token 有效期单位默认30天-1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
activity-timeout: -1
# 是否允许同一账号多地同时登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录)
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token为 false 时每次登录新建一个 token
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token 风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: false
# 是否输出操作日志
is-log: true
```
<!------------- tab:application.properties 风格 ------------->
@ -78,20 +78,20 @@ server.port=8081
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
# token名称同时也是 cookie 名称)
# token 名称(同时也是 cookie 名称)
sa-token.token-name=satoken
# token 有效期(单位:秒)默认30天-1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
sa-token.timeout=2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
sa-token.activity-timeout=-1
# 是否允许同一账号多地同时登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录)
sa-token.active-timeout=-1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
sa-token.is-concurrent=true
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token为 false 时每次登录新建一个 token
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
sa-token.is-share=true
# token 风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
sa-token.token-style=uuid
# 是否输出操作日志
sa-token.is-log=false
sa-token.is-log=true
```
<!---------------------------- tabs:end ---------------------------->

View File

@ -68,18 +68,18 @@ server:
sa-token:
# token 名称(同时也是 cookie 名称)
token-name: satoken
# token 有效期(单位:秒)默认30天-1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
activity-timeout: -1
# 是否允许同一账号多地同时登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录)
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token为 false 时每次登录新建一个 token
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token 风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: false
is-log: true
```
<!------------- tab:app.properties 风格 ------------->
@ -89,20 +89,20 @@ server.port=8081
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
# token名称同时也是 cookie 名称)
# token 名称(同时也是 cookie 名称)
sa-token.token-name=satoken
# token 有效期(单位:秒)默认30天-1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
sa-token.timeout=2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
sa-token.activity-timeout=-1
# 是否允许同一账号多地同时登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录)
sa-token.active-timeout=-1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
sa-token.is-concurrent=true
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token为 false 时每次登录新建一个 token
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
sa-token.is-share=true
# token 风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
sa-token.token-style=uuid
# 是否输出操作日志
sa-token.is-log=false
sa-token.is-log=true
```
<!---------------------------- tabs:end ---------------------------->

View File

@ -14,38 +14,38 @@
sa-token:
# token 名称(同时也是 cookie 名称)
token-name: satoken
# token 有效期单位默认30天-1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
activity-timeout: -1
# 是否允许同一账号多地同时登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录)
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token为 false 时每次登录新建一个 token
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token 风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: false
# 是否输出操作日志
is-log: true
```
<!------------- tab:properties 风格 ------------->
``` properties
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
# token名称同时也是 cookie 名称)
# token 名称(同时也是 cookie 名称)
sa-token.token-name=satoken
# token 有效期(单位:秒)默认30天-1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
sa-token.timeout=2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
sa-token.activity-timeout=-1
# 是否允许同一账号多地同时登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录)
sa-token.active-timeout=-1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
sa-token.is-concurrent=true
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token为 false 时每次登录新建一个 token
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
sa-token.is-share=true
# token 风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
sa-token.token-style=uuid
# 是否输出操作日志
sa-token.is-log=false
sa-token.is-log=true
```
<!---------------------------- tabs:end ---------------------------->
@ -70,7 +70,7 @@ public class SaTokenConfigure {
SaTokenConfig config = new SaTokenConfig();
config.setTokenName("satoken"); // token 名称(同时也是 cookie 名称)
config.setTimeout(30 * 24 * 60 * 60); // token 有效期单位默认30天-1代表永不过期
config.setActivityTimeout(-1); // token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
config.setActiveTimeout(-1); // token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
config.setIsConcurrent(true); // 是否允许同一账号多地同时登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录)
config.setIsShare(true); // 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token为 false 时每次登录新建一个 token
config.setTokenStyle("uuid"); // token 风格
@ -92,7 +92,7 @@ public class SaTokenConfigure {
public void configSaToken(SaTokenConfig config) {
config.setTokenName("satoken"); // token 名称(同时也是 cookie 名称)
config.setTimeout(30 * 24 * 60 * 60); // token 有效期单位默认30天-1代表永不过期
config.setActivityTimeout(-1); // token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
config.setActiveTimeout(-1); // token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
config.setIsConcurrent(true); // 是否允许同一账号多地同时登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录)
config.setIsShare(true); // 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token为 false 时每次登录新建一个 token
config.setTokenStyle("uuid"); // token 风格
@ -116,7 +116,7 @@ public class SaTokenConfigure {
| :-------- | :-------- | :-------- | :-------- |
| tokenName | String | satoken | Token 名称 (同时也是 Cookie 名称、数据持久化前缀) |
| timeout | long | 2592000 | Token 有效期单位默认30天-1代表永不过期 [参考token有效期详解](/fun/token-timeout) |
| activityTimeout | long | -1 | Token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制永不冻结例如可以设置为1800代表30分钟内无操作就过期 [参考token有效期详解](/fun/token-timeout) |
| activeTimeout | long | -1 | Token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制永不冻结例如可以设置为1800代表30分钟内无操作就冻结 [参考token有效期详解](/fun/token-timeout) |
| isConcurrent | Boolean | true | 是否允许同一账号并发登录 (为 true 时允许一起登录,为 false 时新登录挤掉旧登录) |
| isShare | Boolean | true | 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token为 false 时每次登录新建一个 token |
| maxLoginCount | int | 12 | 同一账号最大登录数量,-1代表不限 (只有在 `isConcurrent=true``isShare=false` 时此配置才有效),[详解](/use/config?id=配置项详解maxlogincount) |

View File

@ -89,7 +89,7 @@ public class StpLogicJwtForMixin extends StpLogic {
info.tokenTimeout = getTokenTimeout();
info.sessionTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
info.tokenSessionTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
info.tokenActivityTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
info.tokenActiveTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
info.loginDevice = getLoginDevice();
return info;
}

View File

@ -91,7 +91,7 @@ public class StpLogicJwtForStateless extends StpLogic {
info.tokenTimeout = getTokenTimeout();
info.sessionTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
info.tokenSessionTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
info.tokenActivityTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
info.tokenActiveTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
info.loginDevice = getLoginDevice();
return info;
}

View File

@ -39,7 +39,7 @@ public class AtteStartListener implements JbootAppListener {
SaTokenConfig saTokenConfig = new SaTokenConfig();
saTokenConfig.setTokenStyle(SaTokenConsts.TOKEN_STYLE_SIMPLE_UUID);
saTokenConfig.setTimeout(60*60*4); //登录有效时间4小时
saTokenConfig.setActivityTimeout(30*60); //半小时无操作过期处理
saTokenConfig.setActiveTimeout(30*60); //半小时无操作就冻结 token
saTokenConfig.setIsShare(false);
saTokenConfig.setTokenName("token"); //更换satoken的名称
saTokenConfig.setCookie(new SaCookieConfig().setHttpOnly(true)); //开启cookies的httponly属性

View File

@ -38,7 +38,7 @@ public class Config extends JFinalConfig {
SaTokenConfig saTokenConfig = new SaTokenConfig();
saTokenConfig.setTokenStyle(SaTokenConsts.TOKEN_STYLE_SIMPLE_UUID);
saTokenConfig.setTimeout(60*60*4); //登录有效时间4小时
saTokenConfig.setActivityTimeout(30*60); //半小时无操作过期处理
saTokenConfig.setActiveTimeout(30*60); //半小时无操作就冻结 token
saTokenConfig.setIsShare(false);
saTokenConfig.setTokenName("token"); //更改satoken的cookies名称
SaCookieConfig saCookieConfig = new SaCookieConfig();

View File

@ -1,21 +1,21 @@
# sa-token配置
# sa-token 配置
sa-token:
# token名称 (同时也是cookie名称)
# token 名称 (同时也是 cookie 名称)
token-name: satoken
# token有效期单位s 默认30天, -1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
allow-concurrent-login: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# 是否输出操作日志
is-log: false
# 是否输出操作日志
is-log: true
sa-token-dao: #名字可以随意取

View File

@ -2,19 +2,19 @@
server:
port: 8081
# sa-token配置
# sa-token 配置
sa-token:
# token名称 (同时也是cookie名称)
# token 名称 (同时也是 cookie 名称)
token-name: satoken
# token有效期单位s 默认30天, -1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
is-share: true
# token风格
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik
token-style: uuid
# jwt秘钥
jwt-secret-key: asdasdasifhueuiwyurfewbfjsdafjk

View File

@ -41,8 +41,8 @@ public class SaTokenConfigTest {
config.setTimeout(100204);
Assertions.assertEquals(config.getTimeout(), 100204);
config.setActivityTimeout(1804);
Assertions.assertEquals(config.getActivityTimeout(), 1804);
config.setActiveTimeout(1804);
Assertions.assertEquals(config.getActiveTimeout(), 1804);
config.setIsConcurrent(false);
Assertions.assertEquals(config.getIsConcurrent(), false);
@ -111,7 +111,7 @@ public class SaTokenConfigTest {
SaTokenConfig config = SaTokenConfigFactory.createConfig("sa-token2.properties");
Assertions.assertEquals(config.getTokenName(), "use-token");
Assertions.assertEquals(config.getTimeout(), 9000);
Assertions.assertEquals(config.getActivityTimeout(), 240);
Assertions.assertEquals(config.getActiveTimeout(), 240);
Assertions.assertEquals(config.getIsConcurrent(), false);
Assertions.assertEquals(config.getIsShare(), false);
Assertions.assertEquals(config.getIsLog(), true);

View File

@ -45,7 +45,7 @@ public class TokenInfoTest {
info.setTokenTimeout(1800);
info.setSessionTimeout(120);
info.setTokenSessionTimeout(1800);
info.setTokenActivityTimeout(120);
info.setTokenActiveTimeout(120);
info.setLoginDevice("PC");
info.setTag("xxx");
@ -57,7 +57,7 @@ public class TokenInfoTest {
Assertions.assertEquals(info.getTokenTimeout(), 1800);
Assertions.assertEquals(info.getSessionTimeout(), 120);
Assertions.assertEquals(info.getTokenSessionTimeout(), 1800);
Assertions.assertEquals(info.getTokenActivityTimeout(), 120);
Assertions.assertEquals(info.getTokenActiveTimeout(), 120);
Assertions.assertEquals(info.getLoginDevice(), "PC");
Assertions.assertEquals(info.getTag(), "xxx");

View File

@ -75,7 +75,7 @@ public class BasicsTest {
@BeforeAll
public static void beforeClass() {
System.out.println("\n\n------------------------ 基础测试 star ...");
SaManager.getConfig().setActivityTimeout(180);
SaManager.getConfig().setActiveTimeout(180);
}
// 结束
@ -710,20 +710,20 @@ public class BasicsTest {
Assertions.assertEquals(tokenSession.get("code"), "123456");
}
// 测试临时过期
// 测试token 最低活跃频率
@Test
public void testActivityTimeout() {
public void testActiveTimeout() {
// 登录
StpUtil.login(10001);
Assertions.assertNotNull(StpUtil.getTokenValue());
// 默认跟随全局 timeout
StpUtil.updateLastActivityToNow();
long activityTimeout = StpUtil.getTokenActivityTimeout();
Assertions.assertTrue(activityTimeout <=180 || activityTimeout >=179);
StpUtil.updateLastActiveToNow();
long activeTimeout = StpUtil.getTokenActiveTimeout();
Assertions.assertTrue(activeTimeout <=180 || activeTimeout >=179);
// 不会抛出异常
Assertions.assertDoesNotThrow(() -> StpUtil.checkActivityTimeout());
Assertions.assertDoesNotThrow(() -> StpUtil.checkActiveTimeout());
}
// 测试上下文 API

View File

@ -1,12 +1,12 @@
# token名称 (同时也是cookie名称)
# token 名称 (同时也是 cookie 名称)
tokenName=use-token
# token有效期单位s 默认30天, -1代表永不过期
# token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout=9000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activityTimeout=240
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) =-1
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
activeTimeout=240
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
isConcurrent=false
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token
isShare=false
# token风格
isLog=true
# 是否输出操作日志
isLog=true