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:
parent
48ba6da91a
commit
814a64907a
@ -25,7 +25,7 @@ import java.lang.annotation.Target;
|
|||||||
*
|
*
|
||||||
* <p> 可标注在方法、类上(效果等同于标注在此类的所有方法上)
|
* <p> 可标注在方法、类上(效果等同于标注在此类的所有方法上)
|
||||||
*
|
*
|
||||||
* @author kong
|
* @author click33
|
||||||
* @since 1.10.0
|
* @since 1.10.0
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@ -25,7 +25,7 @@ import java.lang.annotation.Target;
|
|||||||
*
|
*
|
||||||
* <p> 可标注在方法、类上(效果等同于标注在此类的所有方法上)
|
* <p> 可标注在方法、类上(效果等同于标注在此类的所有方法上)
|
||||||
*
|
*
|
||||||
* @author kong
|
* @author click33
|
||||||
* @since 1.35.0
|
* @since 1.35.0
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package cn.dev33.satoken.config;
|
package cn.dev33.satoken.config;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.SaManager;
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@ -37,14 +38,19 @@ public class SaTokenConfig implements Serializable {
|
|||||||
/** token 名称 (同时也是: cookie 名称、提交 token 时参数的名称、存储 token 时的 key 前缀) */
|
/** token 名称 (同时也是: cookie 名称、提交 token 时参数的名称、存储 token 时的 key 前缀) */
|
||||||
private String tokenName = "satoken";
|
private String tokenName = "satoken";
|
||||||
|
|
||||||
/** token 有效期(单位:秒) 默认30天,-1 代表永久 */
|
/** token 有效期(单位:秒) 默认30天,-1 代表永久有效 */
|
||||||
private long timeout = 60 * 60 * 24 * 30;
|
private long timeout = 60 * 60 * 24 * 30;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
* token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
* (例如可以设置为 1800 代表 30 分钟内无操作就冻结)
|
* (例如可以设置为 1800 代表 30 分钟内无操作就冻结)
|
||||||
*/
|
*/
|
||||||
private long activityTimeout = -1;
|
private long activeTimeout = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用动态 activeTimeout 功能,如不需要请设置为 false,节省缓存请求次数
|
||||||
|
*/
|
||||||
|
private Boolean dynamicActiveTimeout = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
* 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
@ -102,7 +108,7 @@ public class SaTokenConfig implements Serializable {
|
|||||||
private Boolean tokenSessionCheckLogin = true;
|
private Boolean tokenSessionCheckLogin = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否打开自动续签 activityTimeout (如果此值为 true, 框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作)
|
* 是否打开自动续签 activeTimeout (如果此值为 true, 框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作)
|
||||||
*/
|
*/
|
||||||
private Boolean autoRenew = true;
|
private Boolean autoRenew = true;
|
||||||
|
|
||||||
@ -189,14 +195,14 @@ public class SaTokenConfig implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return token 有效期(单位:秒) 默认30天,-1 代表永久
|
* @return token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
*/
|
*/
|
||||||
public long getTimeout() {
|
public long getTimeout() {
|
||||||
return timeout;
|
return timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param timeout token 有效期(单位:秒) 默认30天,-1 代表永久
|
* @param timeout token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
* @return 对象自身
|
* @return 对象自身
|
||||||
*/
|
*/
|
||||||
public SaTokenConfig setTimeout(long timeout) {
|
public SaTokenConfig setTimeout(long timeout) {
|
||||||
@ -208,17 +214,33 @@ public class SaTokenConfig implements Serializable {
|
|||||||
* @return token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
* @return token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
* (例如可以设置为 1800 代表 30 分钟内无操作就冻结)
|
* (例如可以设置为 1800 代表 30 分钟内无操作就冻结)
|
||||||
*/
|
*/
|
||||||
public long getActivityTimeout() {
|
public long getActiveTimeout() {
|
||||||
return activityTimeout;
|
return activeTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param activityTimeout token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
* @param activeTimeout token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
* (例如可以设置为 1800 代表 30 分钟内无操作就冻结)
|
* (例如可以设置为 1800 代表 30 分钟内无操作就冻结)
|
||||||
* @return 对象自身
|
* @return 对象自身
|
||||||
*/
|
*/
|
||||||
public SaTokenConfig setActivityTimeout(long activityTimeout) {
|
public SaTokenConfig setActiveTimeout(long activeTimeout) {
|
||||||
this.activityTimeout = activityTimeout;
|
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;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,14 +421,14 @@ public class SaTokenConfig implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 是否打开自动续签 activityTimeout (如果此值为 true, 框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作)
|
* @return 是否打开自动续签 activeTimeout (如果此值为 true, 框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作)
|
||||||
*/
|
*/
|
||||||
public Boolean getAutoRenew() {
|
public Boolean getAutoRenew() {
|
||||||
return autoRenew;
|
return autoRenew;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param autoRenew 是否打开自动续签 activityTimeout (如果此值为 true, 框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作)
|
* @param autoRenew 是否打开自动续签 activeTimeout (如果此值为 true, 框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作)
|
||||||
* @return 对象自身
|
* @return 对象自身
|
||||||
*/
|
*/
|
||||||
public SaTokenConfig setAutoRenew(Boolean autoRenew) {
|
public SaTokenConfig setAutoRenew(Boolean autoRenew) {
|
||||||
@ -633,7 +655,8 @@ public class SaTokenConfig implements Serializable {
|
|||||||
return "SaTokenConfig ["
|
return "SaTokenConfig ["
|
||||||
+ "tokenName=" + tokenName
|
+ "tokenName=" + tokenName
|
||||||
+ ", timeout=" + timeout
|
+ ", timeout=" + timeout
|
||||||
+ ", activityTimeout=" + activityTimeout
|
+ ", activeTimeout=" + activeTimeout
|
||||||
|
+ ", dynamicActiveTimeout=" + dynamicActiveTimeout
|
||||||
+ ", isConcurrent=" + isConcurrent
|
+ ", isConcurrent=" + isConcurrent
|
||||||
+ ", isShare=" + isShare
|
+ ", isShare=" + isShare
|
||||||
+ ", maxLoginCount=" + maxLoginCount
|
+ ", 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ public interface SaTokenListener {
|
|||||||
void doLogoutSession(String id);
|
void doLogoutSession(String id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 每次 Token 续期时触发(注意:是 timeout 续期,而不是 activity-timeout 续期)
|
* 每次 Token 续期时触发(注意:是 timeout 续期,而不是 active-timeout 续期)
|
||||||
*
|
*
|
||||||
* @param tokenValue token 值
|
* @param tokenValue token 值
|
||||||
* @param loginId 账号id
|
* @param loginId 账号id
|
||||||
|
@ -60,6 +60,14 @@ public class SaLoginConfig {
|
|||||||
return create().setTimeout(timeout);
|
return create().setTimeout(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param activeTimeout 指定此次登录 token 最低活跃频率,单位:秒(如未指定,自动取全局配置的 activeTimeout 值)
|
||||||
|
* @return 对象自身
|
||||||
|
*/
|
||||||
|
public static SaLoginModel setActiveTimeout(long activeTimeout) {
|
||||||
|
return create().setActiveTimeout(activeTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param extraData 扩展信息(只在jwt模式下生效)
|
* @param extraData 扩展信息(只在jwt模式下生效)
|
||||||
* @return 登录参数 Model
|
* @return 登录参数 Model
|
||||||
|
@ -47,10 +47,15 @@ public class SaLoginModel {
|
|||||||
public Boolean isLastingCookie = true;
|
public Boolean isLastingCookie = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指定此次登录token的有效期, 单位:秒 (如未指定,自动取全局配置的timeout值)
|
* 指定此次登录 token 有效期,单位:秒 (如未指定,自动取全局配置的 timeout 值)
|
||||||
*/
|
*/
|
||||||
public Long timeout;
|
public Long timeout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定此次登录 token 最低活跃频率,单位:秒(如未指定,则使用全局配置的 activeTimeout 值)
|
||||||
|
*/
|
||||||
|
private Long activeTimeout;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 扩展信息(只在jwt模式下生效)
|
* 扩展信息(只在jwt模式下生效)
|
||||||
*/
|
*/
|
||||||
@ -91,16 +96,6 @@ public class SaLoginModel {
|
|||||||
return isLastingCookie;
|
return isLastingCookie;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return 是否为持久Cookie(临时Cookie在浏览器关闭时会自动删除,持久Cookie在重新打开后依然存在)
|
|
||||||
*/
|
|
||||||
public Boolean getIsLastingCookieOrFalse() {
|
|
||||||
if(isLastingCookie == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return isLastingCookie;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param isLastingCookie 是否为持久Cookie(临时Cookie在浏览器关闭时会自动删除,持久Cookie在重新打开后依然存在)
|
* @param isLastingCookie 是否为持久Cookie(临时Cookie在浏览器关闭时会自动删除,持久Cookie在重新打开后依然存在)
|
||||||
* @return 对象自身
|
* @return 对象自身
|
||||||
@ -111,24 +106,14 @@ public class SaLoginModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 指定此次登录token的有效期, 单位:秒 (如未指定,自动取全局配置的timeout值)
|
* @return 指定此次登录 token 有效期,单位:秒
|
||||||
*/
|
*/
|
||||||
public Long getTimeout() {
|
public Long getTimeout() {
|
||||||
return timeout;
|
return timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return timeout 值 (如果此配置项尚未配置,则取全局配置的值)
|
* @param timeout 指定此次登录 token 有效期,单位:秒 (如未指定,自动取全局配置的 timeout 值)
|
||||||
*/
|
|
||||||
public Long getTimeoutOrGlobalConfig() {
|
|
||||||
if(timeout == null) {
|
|
||||||
timeout = SaManager.getConfig().getTimeout();
|
|
||||||
}
|
|
||||||
return timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param timeout 指定此次登录token的有效期, 单位:秒 (如未指定,自动取全局配置的timeout值)
|
|
||||||
* @return 对象自身
|
* @return 对象自身
|
||||||
*/
|
*/
|
||||||
public SaLoginModel setTimeout(long timeout) {
|
public SaLoginModel setTimeout(long timeout) {
|
||||||
@ -136,6 +121,23 @@ public class SaLoginModel {
|
|||||||
return this;
|
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模式下生效)
|
* @return 扩展信息(只在jwt模式下生效)
|
||||||
*/
|
*/
|
||||||
@ -175,16 +177,6 @@ public class SaLoginModel {
|
|||||||
return isWriteHeader;
|
return isWriteHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return 是否在登录后将 Token 写入到响应头 (如果此配置项尚未配置,则取全局配置的值)
|
|
||||||
*/
|
|
||||||
public Boolean getIsWriteHeaderOrGlobalConfig() {
|
|
||||||
if(isWriteHeader == null) {
|
|
||||||
isWriteHeader = SaManager.getConfig().getIsWriteHeader();
|
|
||||||
}
|
|
||||||
return isWriteHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param isWriteHeader 是否在登录后将 Token 写入到响应头
|
* @param isWriteHeader 是否在登录后将 Token 写入到响应头
|
||||||
* @return 对象自身
|
* @return 对象自身
|
||||||
@ -213,6 +205,7 @@ public class SaLoginModel {
|
|||||||
this.tokenSignTag = tokenSignTag;
|
this.tokenSignTag = tokenSignTag;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* toString
|
* toString
|
||||||
*/
|
*/
|
||||||
@ -222,6 +215,7 @@ public class SaLoginModel {
|
|||||||
+ "device=" + device
|
+ "device=" + device
|
||||||
+ ", isLastingCookie=" + isLastingCookie
|
+ ", isLastingCookie=" + isLastingCookie
|
||||||
+ ", timeout=" + timeout
|
+ ", timeout=" + timeout
|
||||||
|
+ ", activeTimeout=" + activeTimeout
|
||||||
+ ", extraData=" + extraData
|
+ ", extraData=" + extraData
|
||||||
+ ", token=" + token
|
+ ", token=" + token
|
||||||
+ ", isWriteHeader=" + isWriteHeader
|
+ ", 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模式下生效)
|
* 写入扩展数据(只在jwt模式下生效)
|
||||||
* @param key 键
|
* @param key 键
|
||||||
@ -288,7 +312,7 @@ public class SaLoginModel {
|
|||||||
}
|
}
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建对象,初始化默认值
|
* 构建对象,初始化默认值
|
||||||
* @return 对象自身
|
* @return 对象自身
|
||||||
|
@ -30,7 +30,7 @@ package cn.dev33.satoken.stp;
|
|||||||
* "tokenTimeout": 2591977, // token剩余有效期 (单位: 秒)
|
* "tokenTimeout": 2591977, // token剩余有效期 (单位: 秒)
|
||||||
* "sessionTimeout": 2591977, // Account-Session剩余有效时间 (单位: 秒)
|
* "sessionTimeout": 2591977, // Account-Session剩余有效时间 (单位: 秒)
|
||||||
* "tokenSessionTimeout": -2, // Token-Session剩余有效时间 (单位: 秒) (-2表示系统中不存在这个缓存)
|
* "tokenSessionTimeout": -2, // Token-Session剩余有效时间 (单位: 秒) (-2表示系统中不存在这个缓存)
|
||||||
* "tokenActivityTimeout": -1, // token剩余无操作有效时间 (单位: 秒)
|
* "tokenActiveTimeout": -1, // Token 距离被冻结还剩多少时间 (单位: 秒)
|
||||||
* "loginDevice": "default-device" // 登录设备类型
|
* "loginDevice": "default-device" // 登录设备类型
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
@ -65,8 +65,8 @@ public class SaTokenInfo {
|
|||||||
/** Token-Session 剩余有效时间(单位: 秒) */
|
/** Token-Session 剩余有效时间(单位: 秒) */
|
||||||
public long tokenSessionTimeout;
|
public long tokenSessionTimeout;
|
||||||
|
|
||||||
/** token 剩余无操作有效时间(单位: 秒) */
|
/** token 距离被冻结还剩多少时间(单位: 秒) */
|
||||||
public long tokenActivityTimeout;
|
public long tokenActiveTimeout;
|
||||||
|
|
||||||
/** 登录设备类型 */
|
/** 登录设备类型 */
|
||||||
public String loginDevice;
|
public String loginDevice;
|
||||||
@ -189,17 +189,17 @@ public class SaTokenInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return token 剩余无操作有效时间(单位: 秒)
|
* @return token 距离被冻结还剩多少时间(单位: 秒)
|
||||||
*/
|
*/
|
||||||
public long getTokenActivityTimeout() {
|
public long getTokenActiveTimeout() {
|
||||||
return tokenActivityTimeout;
|
return tokenActiveTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param tokenActivityTimeout token 剩余无操作有效时间(单位: 秒)
|
* @param tokenActiveTimeout token 距离被冻结还剩多少时间(单位: 秒)
|
||||||
*/
|
*/
|
||||||
public void setTokenActivityTimeout(long tokenActivityTimeout) {
|
public void setTokenActiveTimeout(long tokenActiveTimeout) {
|
||||||
this.tokenActivityTimeout = tokenActivityTimeout;
|
this.tokenActiveTimeout = tokenActiveTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -238,7 +238,7 @@ public class SaTokenInfo {
|
|||||||
return "SaTokenInfo [tokenName=" + tokenName + ", tokenValue=" + tokenValue + ", isLogin=" + isLogin
|
return "SaTokenInfo [tokenName=" + tokenName + ", tokenValue=" + tokenValue + ", isLogin=" + isLogin
|
||||||
+ ", loginId=" + loginId + ", loginType=" + loginType + ", tokenTimeout=" + tokenTimeout
|
+ ", loginId=" + loginId + ", loginType=" + loginType + ", tokenTimeout=" + tokenTimeout
|
||||||
+ ", sessionTimeout=" + sessionTimeout + ", tokenSessionTimeout=" + tokenSessionTimeout
|
+ ", sessionTimeout=" + sessionTimeout + ", tokenSessionTimeout=" + tokenSessionTimeout
|
||||||
+ ", tokenActivityTimeout=" + tokenActivityTimeout + ", loginDevice=" + loginDevice + ", tag=" + tag
|
+ ", tokenActiveTimeout=" + tokenActiveTimeout + ", loginDevice=" + loginDevice + ", tag=" + tag
|
||||||
+ "]";
|
+ "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ import cn.dev33.satoken.session.TokenSign;
|
|||||||
import cn.dev33.satoken.strategy.SaStrategy;
|
import cn.dev33.satoken.strategy.SaStrategy;
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
import cn.dev33.satoken.util.SaTokenConsts;
|
import cn.dev33.satoken.util.SaTokenConsts;
|
||||||
|
import cn.dev33.satoken.util.SaValue2Box;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -342,7 +343,7 @@ public class StpLogic {
|
|||||||
info.tokenTimeout = getTokenTimeout();
|
info.tokenTimeout = getTokenTimeout();
|
||||||
info.sessionTimeout = getSessionTimeout();
|
info.sessionTimeout = getSessionTimeout();
|
||||||
info.tokenSessionTimeout = getTokenSessionTimeout();
|
info.tokenSessionTimeout = getTokenSessionTimeout();
|
||||||
info.tokenActivityTimeout = getTokenActivityTimeout();
|
info.tokenActiveTimeout = getTokenActiveTimeout();
|
||||||
info.loginDevice = getLoginDevice();
|
info.loginDevice = getLoginDevice();
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@ -401,7 +402,7 @@ public class StpLogic {
|
|||||||
// 1、创建会话
|
// 1、创建会话
|
||||||
String token = createLoginSession(id, loginModel);
|
String token = createLoginSession(id, loginModel);
|
||||||
|
|
||||||
// 2、在当前客户端注入Token
|
// 2、在当前客户端注入 token
|
||||||
setTokenValue(token, loginModel);
|
setTokenValue(token, loginModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,8 +446,10 @@ public class StpLogic {
|
|||||||
// 6、保存 token -> id 的映射关系,方便日后根据 token 找账号 id
|
// 6、保存 token -> id 的映射关系,方便日后根据 token 找账号 id
|
||||||
saveTokenToIdMapping(tokenValue, id, loginModel.getTimeout());
|
saveTokenToIdMapping(tokenValue, id, loginModel.getTimeout());
|
||||||
|
|
||||||
// 7、写入这个 token 的最后活跃时间 token-last-activity
|
// 7、写入这个 token 的最后活跃时间 token-last-active
|
||||||
setLastActivityToNow(tokenValue);
|
if(isOpenCheckActiveTimeout()) {
|
||||||
|
setLastActiveToNow(tokenValue, loginModel.getActiveTimeout(), loginModel.getTimeoutOrGlobalConfig());
|
||||||
|
}
|
||||||
|
|
||||||
// 8、$$ 发布全局事件:账号 xxx 登录成功
|
// 8、$$ 发布全局事件:账号 xxx 登录成功
|
||||||
SaTokenEventCenter.doLogin(loginType, id, tokenValue, loginModel);
|
SaTokenEventCenter.doLogin(loginType, id, tokenValue, loginModel);
|
||||||
@ -541,10 +544,15 @@ public class StpLogic {
|
|||||||
// 如果不支持,开发者却传入了 extra 扩展参数,那么就打印警告信息
|
// 如果不支持,开发者却传入了 extra 扩展参数,那么就打印警告信息
|
||||||
Map<String, Object> extraData = loginModel.getExtraData();
|
Map<String, Object> extraData = loginModel.getExtraData();
|
||||||
if(extraData != null && extraData.size() > 0) {
|
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());
|
storage.delete(splicingKeyJustCreatedSave());
|
||||||
|
|
||||||
// 4、清除当前上下文的 [ 活跃度校验 check 标记 ]
|
// 4、清除当前上下文的 [ 活跃度校验 check 标记 ]
|
||||||
storage.delete(SaTokenConsts.TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY);
|
storage.delete(SaTokenConsts.TOKEN_ACTIVE_TIMEOUT_CHECKED_KEY);
|
||||||
|
|
||||||
// 5、清除这个 token 的其它相关信息
|
// 5、清除这个 token 的其它相关信息
|
||||||
logoutByTokenValue(tokenValue);
|
logoutByTokenValue(tokenValue);
|
||||||
@ -606,7 +614,7 @@ public class StpLogic {
|
|||||||
session.removeTokenSign(tokenValue);
|
session.removeTokenSign(tokenValue);
|
||||||
|
|
||||||
// 2.3、清除这个 token 的最后活跃时间记录
|
// 2.3、清除这个 token 的最后活跃时间记录
|
||||||
clearLastActivity(tokenValue);
|
clearLastActive(tokenValue);
|
||||||
|
|
||||||
// 2.4、清除 token -> id 的映射关系
|
// 2.4、清除 token -> id 的映射关系
|
||||||
deleteTokenToIdMapping(tokenValue);
|
deleteTokenToIdMapping(tokenValue);
|
||||||
@ -654,7 +662,7 @@ public class StpLogic {
|
|||||||
session.removeTokenSign(tokenValue);
|
session.removeTokenSign(tokenValue);
|
||||||
|
|
||||||
// 3.3、清除这个 token 的最后活跃时间记录
|
// 3.3、清除这个 token 的最后活跃时间记录
|
||||||
clearLastActivity(tokenValue);
|
clearLastActive(tokenValue);
|
||||||
|
|
||||||
// 3.4、清除 token -> id 的映射关系
|
// 3.4、清除 token -> id 的映射关系
|
||||||
deleteTokenToIdMapping(tokenValue);
|
deleteTokenToIdMapping(tokenValue);
|
||||||
@ -677,7 +685,7 @@ public class StpLogic {
|
|||||||
*/
|
*/
|
||||||
public void logoutByTokenValue(String tokenValue) {
|
public void logoutByTokenValue(String tokenValue) {
|
||||||
// 1、清除这个 token 的最后活跃时间记录
|
// 1、清除这个 token 的最后活跃时间记录
|
||||||
clearLastActivity(tokenValue);
|
clearLastActive(tokenValue);
|
||||||
|
|
||||||
// 2、清除这个 token 的 Token-Session 对象
|
// 2、清除这个 token 的 Token-Session 对象
|
||||||
deleteTokenSession(tokenValue);
|
deleteTokenSession(tokenValue);
|
||||||
@ -736,7 +744,7 @@ public class StpLogic {
|
|||||||
session.removeTokenSign(tokenValue);
|
session.removeTokenSign(tokenValue);
|
||||||
|
|
||||||
// 2.3、清除这个 token 的最后活跃时间记录
|
// 2.3、清除这个 token 的最后活跃时间记录
|
||||||
clearLastActivity(tokenValue);
|
clearLastActive(tokenValue);
|
||||||
|
|
||||||
// 2.4、将此 token 标记为:已被踢下线
|
// 2.4、将此 token 标记为:已被踢下线
|
||||||
updateTokenToIdMapping(tokenValue, NotLoginException.KICK_OUT);
|
updateTokenToIdMapping(tokenValue, NotLoginException.KICK_OUT);
|
||||||
@ -761,7 +769,7 @@ public class StpLogic {
|
|||||||
*/
|
*/
|
||||||
public void kickoutByTokenValue(String tokenValue) {
|
public void kickoutByTokenValue(String tokenValue) {
|
||||||
// 1、清除这个 token 的最后活跃时间记录
|
// 1、清除这个 token 的最后活跃时间记录
|
||||||
clearLastActivity(tokenValue);
|
clearLastActive(tokenValue);
|
||||||
|
|
||||||
// 2、此处不需要清除它的 Token-Session 对象
|
// 2、此处不需要清除它的 Token-Session 对象
|
||||||
// deleteTokenSession(tokenValue);
|
// deleteTokenSession(tokenValue);
|
||||||
@ -808,7 +816,7 @@ public class StpLogic {
|
|||||||
session.removeTokenSign(tokenValue);
|
session.removeTokenSign(tokenValue);
|
||||||
|
|
||||||
// 2.3、清除这个 token 的最后活跃时间记录
|
// 2.3、清除这个 token 的最后活跃时间记录
|
||||||
clearLastActivity(tokenValue);
|
clearLastActive(tokenValue);
|
||||||
|
|
||||||
// 2.4、将此 token 标记为:已被顶下线
|
// 2.4、将此 token 标记为:已被顶下线
|
||||||
updateTokenToIdMapping(tokenValue, NotLoginException.BE_REPLACED);
|
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);
|
throw NotLoginException.newInstance(loginType, KICK_OUT, KICK_OUT_MESSAGE, tokenValue).setCode(SaErrorCode.CODE_11015);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7、检查此 token 的最后活跃时间是否已经超过了 activity-timeout 的限制,
|
// 7、检查此 token 的最后活跃时间是否已经超过了 active-timeout 的限制,
|
||||||
// 如果是则代表其已被冻结,需要抛出:token 已过期
|
// 如果是则代表其已被冻结,需要抛出:token 已过期
|
||||||
checkActivityTimeout(tokenValue);
|
checkActiveTimeout(tokenValue);
|
||||||
|
|
||||||
// ------ 至此,loginId 已经是一个合法的值,代表当前会话是一个正常的登录状态了
|
// ------ 至此,loginId 已经是一个合法的值,代表当前会话是一个正常的登录状态了
|
||||||
|
|
||||||
// 8、如果配置了自动续签功能, 则: 更新这个 token 的最后活跃时间 (注意此处的续签是在续 activity-timeout,而非 timeout)
|
// 8、如果配置了自动续签功能, 则: 更新这个 token 的最后活跃时间 (注意此处的续签是在续 active-timeout,而非 timeout)
|
||||||
if(getConfig().getAutoRenew()) {
|
if(isOpenCheckActiveTimeout() && getConfig().getAutoRenew()) {
|
||||||
updateLastActivityToNow(tokenValue);
|
updateLastActiveToNow(tokenValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 9、返回 loginId
|
// 9、返回 loginId
|
||||||
@ -947,7 +955,7 @@ public class StpLogic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 4、如果 token 已被冻结,也返回 null
|
// 4、如果 token 已被冻结,也返回 null
|
||||||
if(getTokenActivityTimeoutByToken(tokenValue) == SaTokenDao.NOT_VALUE_EXPIRE) {
|
if(getTokenActiveTimeoutByToken(tokenValue) == SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1285,7 +1293,9 @@ public class StpLogic {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 写入此 token 的最后活跃时间
|
// 写入此 token 的最后活跃时间
|
||||||
setLastActivityToNow(tokenValue);
|
if(isOpenCheckActiveTimeout()) {
|
||||||
|
setLastActiveToNow(tokenValue, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
// 在当前上下文写入此 TokenValue
|
// 在当前上下文写入此 TokenValue
|
||||||
setTokenValue(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 活跃度校验, 则立即返回,无需操作
|
// 如果提供的 timeout 为null,则使用全局配置的 timeout 值
|
||||||
if(SaFoxUtil.isEmpty(tokenValue) || ! isOpenActivityCheck() ) {
|
SaTokenConfig config = getConfig();
|
||||||
return;
|
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 的 [ 最后活跃时间记录 ]
|
* 清除指定 Token 的 [ 最后活跃时间记录 ]
|
||||||
*
|
*
|
||||||
* @param tokenValue 指定 token
|
* @param tokenValue 指定 token
|
||||||
*/
|
*/
|
||||||
protected void clearLastActivity(String tokenValue) {
|
protected void clearLastActive(String tokenValue) {
|
||||||
|
|
||||||
// 如果提供的 token 无效,或者配置没有打开 token 活跃度校验, 则立即返回,无需操作
|
// 如果提供的 token 无效,或者配置没有打开 token 活跃度校验, 则立即返回,无需操作
|
||||||
if(SaFoxUtil.isEmpty(tokenValue) || ! isOpenActivityCheck() ) {
|
if(SaFoxUtil.isEmpty(tokenValue) || ! isOpenCheckActiveTimeout() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除 [ 最后活跃时间 ]
|
// 删除 [ 最后活跃时间 ]
|
||||||
getSaTokenDao().delete(splicingKeyLastActivityTime(tokenValue));
|
String key = splicingKeyLastActiveTime(tokenValue);
|
||||||
|
getSaTokenDao().delete(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1356,73 +1405,72 @@ public class StpLogic {
|
|||||||
*
|
*
|
||||||
* @param tokenValue 指定 token
|
* @param tokenValue 指定 token
|
||||||
*/
|
*/
|
||||||
public void checkActivityTimeout(String tokenValue) {
|
public void checkActiveTimeout(String tokenValue) {
|
||||||
|
|
||||||
// 如果提供的 token 无效,或者配置没有打开 token 活跃度校验, 则立即返回,无需操作
|
// 如果提供的 token 无效,或者配置没有打开 token 活跃度校验, 则立即返回,无需操作
|
||||||
if(SaFoxUtil.isEmpty(tokenValue) || ! isOpenActivityCheck() ) {
|
if(SaFoxUtil.isEmpty(tokenValue) || ! isOpenCheckActiveTimeout() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果本次请求已经有了 [ 检查标记 ],说明已经校验过了,此时无需重复校验,立即返回
|
// 下面开始校验这个 token 是否已被冻结
|
||||||
|
// storage.get(key, () -> {}) 可以避免一次请求多次校验,造成不必要的性能消耗
|
||||||
SaStorage storage = SaHolder.getStorage();
|
SaStorage storage = SaHolder.getStorage();
|
||||||
if(storage.get(SaTokenConsts.TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY) != null) {
|
storage.get(SaTokenConsts.TOKEN_ACTIVE_TIMEOUT_CHECKED_KEY, () -> {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------ 下面开始校验这个 token 是否已被冻结
|
// 1、获取这个 token 的剩余活跃有效期
|
||||||
|
long activeTimeout = getTokenActiveTimeoutByToken(tokenValue);
|
||||||
|
|
||||||
// 1、获取这个 token 的剩余活跃有效期
|
// 2、值为 -1 代表此 token 已经被设置永不冻结,无须继续验证
|
||||||
long timeout = getTokenActivityTimeoutByToken(tokenValue);
|
if(activeTimeout == SaTokenDao.NEVER_EXPIRE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// 2、值为 -1 代表此 token 已经被设置永不冻结,无须继续验证
|
// 3、值为 -2 代表已被冻结,此时需要抛出异常
|
||||||
if(timeout == SaTokenDao.NEVER_EXPIRE) {
|
if(activeTimeout == SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||||
// 此句代码含义参考最下面
|
throw NotLoginException.newInstance(loginType, TOKEN_FREEZE, TOKEN_FREEZE_MESSAGE, tokenValue).setCode(SaErrorCode.CODE_11016);
|
||||||
storage.set(SaTokenConsts.TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY, true);
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3、值为 -2 代表已被冻结,此时需要抛出异常
|
// --- 验证通过
|
||||||
if(timeout == SaTokenDao.NOT_VALUE_EXPIRE) {
|
return true;
|
||||||
throw NotLoginException.newInstance(loginType, TOKEN_FREEZE, TOKEN_FREEZE_MESSAGE, tokenValue).setCode(SaErrorCode.CODE_11016);
|
});
|
||||||
}
|
|
||||||
// --- 至此,验证已通过
|
|
||||||
|
|
||||||
// 4、打上 [ 检查标记 ],标记一下当前请求已经通过校验,避免一次请求多次校验,造成不必要的性能消耗
|
|
||||||
storage.set(SaTokenConsts.TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查当前 token 是否已被冻结,如果是则抛出异常
|
* 检查当前 token 是否已被冻结,如果是则抛出异常
|
||||||
*/
|
*/
|
||||||
public void checkActivityTimeout() {
|
public void checkActiveTimeout() {
|
||||||
checkActivityTimeout(getTokenValue());
|
checkActiveTimeout(getTokenValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 续签指定 token:将这个 token 的 [ 最后活跃时间 ] 更新为当前时间戳
|
* 获取指定 token 在缓存中的 activeTimeout 值,如果不存在则返回 null
|
||||||
*
|
*
|
||||||
* @param tokenValue 指定token
|
* @param tokenValue 指定token
|
||||||
*/
|
* @return /
|
||||||
public void updateLastActivityToNow(String tokenValue) {
|
*/
|
||||||
// 如果提供的 token 无效,或者配置没有打开 token 活跃度校验, 则立即返回,无需操作
|
public Long getTokenUseActiveTimeout(String tokenValue) {
|
||||||
if(SaFoxUtil.isEmpty(tokenValue) || ! isOpenActivityCheck() ) {
|
// 先取出这个 token 的最后活跃时间值
|
||||||
return;
|
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();
|
||||||
}
|
}
|
||||||
|
return activeTimeout;
|
||||||
// 将这个 token 的 [ 最后活跃时间 ] 更新为当前时间戳
|
}
|
||||||
getSaTokenDao().update(splicingKeyLastActivityTime(tokenValue), String.valueOf(System.currentTimeMillis()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 续签当前 token:(将 [最后操作时间] 更新为当前时间戳)
|
|
||||||
* <h2>
|
|
||||||
* 请注意: 即使 token 已被冻结 也可续签成功,
|
|
||||||
* 如果此场景下需要提示续签失败,可在此之前调用 checkActivityTimeout() 强制检查是否冻结即可
|
|
||||||
* </h2>
|
|
||||||
*/
|
|
||||||
public void updateLastActivityToNow() {
|
|
||||||
updateLastActivityToNow(getTokenValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------- 过期时间相关 -------------------
|
// ------------------- 过期时间相关 -------------------
|
||||||
@ -1499,8 +1547,8 @@ public class StpLogic {
|
|||||||
*
|
*
|
||||||
* @return /
|
* @return /
|
||||||
*/
|
*/
|
||||||
public long getTokenActivityTimeout() {
|
public long getTokenActiveTimeout() {
|
||||||
return getTokenActivityTimeoutByToken(getTokenValue());
|
return getTokenActiveTimeoutByToken(getTokenValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1509,10 +1557,10 @@ public class StpLogic {
|
|||||||
* @param tokenValue 指定 token
|
* @param tokenValue 指定 token
|
||||||
* @return /
|
* @return /
|
||||||
*/
|
*/
|
||||||
public long getTokenActivityTimeoutByToken(String tokenValue) {
|
public long getTokenActiveTimeoutByToken(String tokenValue) {
|
||||||
|
|
||||||
// 如果全局配置了永不冻结, 则返回 -1
|
// 如果全局配置了永不冻结, 则返回 -1
|
||||||
if( ! isOpenActivityCheck() ) {
|
if( ! isOpenCheckActiveTimeout() ) {
|
||||||
return SaTokenDao.NEVER_EXPIRE;
|
return SaTokenDao.NEVER_EXPIRE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1524,27 +1572,32 @@ public class StpLogic {
|
|||||||
// ------ 开始查询
|
// ------ 开始查询
|
||||||
|
|
||||||
// 1、先获取这个 token 的最后活跃时间,13位时间戳
|
// 1、先获取这个 token 的最后活跃时间,13位时间戳
|
||||||
String keyLastActivityTime = splicingKeyLastActivityTime(tokenValue);
|
String key = splicingKeyLastActiveTime(tokenValue);
|
||||||
String lastActivityTimeString = getSaTokenDao().get(keyLastActivityTime);
|
String lastActiveTimeString = getSaTokenDao().get(key);
|
||||||
|
|
||||||
|
|
||||||
// 2、如果查不到,返回-2
|
// 2、如果查不到,返回-2
|
||||||
if(lastActivityTimeString == null) {
|
if(lastActiveTimeString == null) {
|
||||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3、计算最后活跃时间 和 此时此刻 的时间差
|
// 3、计算最后活跃时间 距离 此时此刻 的时间差
|
||||||
// 计算公式为: (当前时间 - 最后活跃时间) / 1000
|
// 计算公式为: (当前时间 - 最后活跃时间) / 1000
|
||||||
long lastActivityTime = Long.parseLong(lastActivityTimeString);
|
SaValue2Box box = new SaValue2Box(lastActiveTimeString);
|
||||||
long apartSecond = (System.currentTimeMillis() - lastActivityTime) / 1000;
|
long lastActiveTime = box.getValue1AsLong();
|
||||||
|
// 实际时间差
|
||||||
|
long timeDiff = (System.currentTimeMillis() - lastActiveTime) / 1000;
|
||||||
|
// 该 token 允许的时间差
|
||||||
|
long allowTimeDiff = getTokenUseActiveTimeoutOrGlobalConfig(tokenValue);
|
||||||
|
|
||||||
// 4、校验这个时间差是否超过了允许的值
|
// 4、校验这个时间差是否超过了允许的值
|
||||||
// 计算公式为: 允许的最大时间差 - 实际时间差,判断是否 < 0, 如果是则代表已经被冻结 ,返回-2
|
// 计算公式为: 允许的最大时间差 - 实际时间差,判断是否 < 0, 如果是则代表已经被冻结 ,返回-2
|
||||||
long timeout = getConfig().getActivityTimeout() - apartSecond;
|
long activeTimeout = allowTimeDiff - timeDiff;
|
||||||
if(timeout < 0) {
|
if(activeTimeout < 0) {
|
||||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||||
} else {
|
} else {
|
||||||
// 否则代表没冻结,返回剩余有效时间
|
// 否则代表没冻结,返回剩余有效时间
|
||||||
return timeout;
|
return activeTimeout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1597,8 +1650,8 @@ public class StpLogic {
|
|||||||
getSessionByLoginId(loginId).updateMinTimeout(timeout);
|
getSessionByLoginId(loginId).updateMinTimeout(timeout);
|
||||||
|
|
||||||
// 5、更新此 token 的最后活跃时间
|
// 5、更新此 token 的最后活跃时间
|
||||||
if(isOpenActivityCheck()) {
|
if(isOpenCheckActiveTimeout()) {
|
||||||
dao.updateTimeout(splicingKeyLastActivityTime(tokenValue), timeout);
|
dao.updateTimeout(splicingKeyLastActiveTime(tokenValue), timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6、$$ 发布事件:某某 token 被续期了
|
// 6、$$ 发布事件:某某 token 被续期了
|
||||||
@ -2603,8 +2656,8 @@ public class StpLogic {
|
|||||||
* @param tokenValue token值
|
* @param tokenValue token值
|
||||||
* @return key
|
* @return key
|
||||||
*/
|
*/
|
||||||
public String splicingKeyLastActivityTime(String tokenValue) {
|
public String splicingKeyLastActiveTime(String tokenValue) {
|
||||||
return getConfig().getTokenName() + ":" + loginType + ":last-activity:" + tokenValue;
|
return getConfig().getTokenName() + ":" + loginType + ":last-active:" + tokenValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2677,8 +2730,8 @@ public class StpLogic {
|
|||||||
*
|
*
|
||||||
* @return /
|
* @return /
|
||||||
*/
|
*/
|
||||||
public boolean isOpenActivityCheck() {
|
public boolean isOpenCheckActiveTimeout() {
|
||||||
return getConfig().getActivityTimeout() != SaTokenDao.NEVER_EXPIRE;
|
return getConfig().getActiveTimeout() != SaTokenDao.NEVER_EXPIRE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,7 +26,7 @@ import java.util.List;
|
|||||||
* Sa-Token 权限认证工具类
|
* Sa-Token 权限认证工具类
|
||||||
*
|
*
|
||||||
* @author click33
|
* @author click33
|
||||||
* @since 1.10.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public class StpUtil {
|
public class StpUtil {
|
||||||
|
|
||||||
@ -493,26 +493,26 @@ public class StpUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------- Activity-Timeout token 最低活跃度 验证相关 -------------------
|
// ------------------- Active-Timeout token 最低活跃度 验证相关 -------------------
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查当前 token 是否已被冻结,如果是则抛出异常
|
|
||||||
*/
|
|
||||||
public static void checkActivityTimeout() {
|
|
||||||
stpLogic.checkActivityTimeout();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 续签当前 token:(将 [最后操作时间] 更新为当前时间戳)
|
* 续签当前 token:(将 [最后操作时间] 更新为当前时间戳)
|
||||||
* <h2>
|
* <h2>
|
||||||
* 请注意: 即使 token 已被冻结 也可续签成功,
|
* 请注意: 即使 token 已被冻结 也可续签成功,
|
||||||
* 如果此场景下需要提示续签失败,可在此之前调用 checkActivityTimeout() 强制检查是否冻结即可
|
* 如果此场景下需要提示续签失败,可在此之前调用 checkActiveTimeout() 强制检查是否冻结即可
|
||||||
* </h2>
|
* </h2>
|
||||||
*/
|
*/
|
||||||
public static void updateLastActivityToNow() {
|
public static void updateLastActiveToNow() {
|
||||||
stpLogic.updateLastActivityToNow();
|
stpLogic.updateLastActiveToNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查当前 token 是否已被冻结,如果是则抛出异常
|
||||||
|
*/
|
||||||
|
public static void checkActiveTimeout() {
|
||||||
|
stpLogic.checkActiveTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------- 过期时间相关 -------------------
|
// ------------------- 过期时间相关 -------------------
|
||||||
|
|
||||||
@ -558,8 +558,8 @@ public class StpUtil {
|
|||||||
*
|
*
|
||||||
* @return /
|
* @return /
|
||||||
*/
|
*/
|
||||||
public static long getTokenActivityTimeout() {
|
public static long getTokenActiveTimeout() {
|
||||||
return stpLogic.getTokenActivityTimeout();
|
return stpLogic.getTokenActiveTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,9 +67,9 @@ public class SaTokenConsts {
|
|||||||
public static final String JUST_CREATED_NOT_PREFIX = "JUST_CREATED_NOT_PREFIX_";
|
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 标记: 在登录时,默认使用的设备类型
|
* 常量 key 标记: 在登录时,默认使用的设备类型
|
||||||
@ -193,6 +193,13 @@ public class SaTokenConsts {
|
|||||||
* 请更换为 JUST_CREATED
|
* 请更换为 JUST_CREATED
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@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;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -111,7 +111,7 @@ public class LoginAuthController {
|
|||||||
System.out.println("当前登录账号的类型:" + info.getLoginType());
|
System.out.println("当前登录账号的类型:" + info.getLoginType());
|
||||||
System.out.println("当前登录客户端的设备类型:" + info.getLoginDevice());
|
System.out.println("当前登录客户端的设备类型:" + info.getLoginDevice());
|
||||||
System.out.println("当前 Token 的剩余有效期:" + info.getTokenTimeout()); // 单位:秒,-1代表永久有效,-2代表值不存在
|
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("当前 Account-Session 的剩余有效期" + info.getSessionTimeout()); // 单位:秒,-1代表永久有效,-2代表值不存在
|
||||||
System.out.println("当前 Token-Session 的剩余有效期" + info.getTokenSessionTimeout()); // 单位:秒,-1代表永久有效,-2代表值不存在
|
System.out.println("当前 Token-Session 的剩余有效期" + info.getTokenSessionTimeout()); // 单位:秒,-1代表永久有效,-2代表值不存在
|
||||||
|
|
||||||
|
@ -7,17 +7,15 @@ import cn.dev33.satoken.session.SaSession;
|
|||||||
import cn.dev33.satoken.stp.SaLoginModel;
|
import cn.dev33.satoken.stp.SaLoginModel;
|
||||||
import cn.dev33.satoken.stp.SaTokenInfo;
|
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||||
import cn.dev33.satoken.stp.StpLogic;
|
import cn.dev33.satoken.stp.StpLogic;
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sa-Token 权限认证工具类 (User版)
|
* Sa-Token 权限认证工具类 (User 版)
|
||||||
*
|
*
|
||||||
* @author click33
|
* @author click33
|
||||||
* @since <= 1.34.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
@Component
|
|
||||||
public class StpUserUtil {
|
public class StpUserUtil {
|
||||||
|
|
||||||
private StpUserUtil() {}
|
private StpUserUtil() {}
|
||||||
@ -25,7 +23,7 @@ public class StpUserUtil {
|
|||||||
/**
|
/**
|
||||||
* 多账号体系下的类型标识
|
* 多账号体系下的类型标识
|
||||||
*/
|
*/
|
||||||
public static final String TYPE = "user";
|
public static final String TYPE = "login";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 底层使用的 StpLogic 对象
|
* 底层使用的 StpLogic 对象
|
||||||
@ -483,24 +481,24 @@ public class StpUserUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------- Activity-Timeout token 最低活跃度 验证相关 -------------------
|
// ------------------- Active-Timeout token 最低活跃度 验证相关 -------------------
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查当前 token 是否已被冻结,如果是则抛出异常
|
|
||||||
*/
|
|
||||||
public static void checkActivityTimeout() {
|
|
||||||
stpLogic.checkActivityTimeout();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 续签当前 token:(将 [最后操作时间] 更新为当前时间戳)
|
* 续签当前 token:(将 [最后操作时间] 更新为当前时间戳)
|
||||||
* <h2>
|
* <h2>
|
||||||
* 请注意: 即使 token 已被冻结 也可续签成功,
|
* 请注意: 即使 token 已被冻结 也可续签成功,
|
||||||
* 如果此场景下需要提示续签失败,可在此之前调用 checkActivityTimeout() 强制检查是否冻结即可
|
* 如果此场景下需要提示续签失败,可在此之前调用 checkActiveTimeout() 强制检查是否冻结即可
|
||||||
* </h2>
|
* </h2>
|
||||||
*/
|
*/
|
||||||
public static void updateLastActivityToNow() {
|
public static void updateLastActiveToNow() {
|
||||||
stpLogic.updateLastActivityToNow();
|
stpLogic.updateLastActiveToNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查当前 token 是否已被冻结,如果是则抛出异常
|
||||||
|
*/
|
||||||
|
public static void checkActiveTimeout() {
|
||||||
|
stpLogic.checkActiveTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -548,8 +546,8 @@ public class StpUserUtil {
|
|||||||
*
|
*
|
||||||
* @return /
|
* @return /
|
||||||
*/
|
*/
|
||||||
public static long getTokenActivityTimeout() {
|
public static long getTokenActiveTimeout() {
|
||||||
return stpLogic.getTokenActivityTimeout();
|
return stpLogic.getTokenActiveTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,22 +2,22 @@
|
|||||||
server:
|
server:
|
||||||
port: 8081
|
port: 8081
|
||||||
|
|
||||||
# sa-token配置
|
# sa-token 配置
|
||||||
sa-token:
|
sa-token:
|
||||||
# token名称 (同时也是cookie名称)
|
# token 名称 (同时也是 cookie 名称)
|
||||||
token-name: satoken
|
token-name: satoken
|
||||||
# token有效期,单位s 默认30天, -1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: -1
|
||||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
is-concurrent: true
|
is-concurrent: true
|
||||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
is-share: true
|
is-share: true
|
||||||
# token风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
token-style: uuid
|
token-style: uuid
|
||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
is-log: false
|
is-log: true
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
# redis配置
|
# redis配置
|
||||||
|
@ -2,21 +2,21 @@
|
|||||||
server:
|
server:
|
||||||
port: 8081
|
port: 8081
|
||||||
|
|
||||||
# sa-token配置
|
# sa-token 配置
|
||||||
sa-token:
|
sa-token:
|
||||||
# token名称 (同时也是cookie名称)
|
# token 名称 (同时也是 cookie 名称)
|
||||||
token-name: satoken
|
token-name: satoken
|
||||||
# token有效期,单位s 默认30天, -1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: -1
|
||||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
is-concurrent: true
|
is-concurrent: true
|
||||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
is-share: true
|
is-share: true
|
||||||
# token风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
token-style: uuid
|
token-style: uuid
|
||||||
# 是否打印操作日志
|
# 是否输出操作日志
|
||||||
is-log: true
|
is-log: true
|
||||||
# jwt秘钥
|
# jwt秘钥
|
||||||
jwt-secret-key: asdasdasifhueuiwyurfewbfjsdafjk
|
jwt-secret-key: asdasdasifhueuiwyurfewbfjsdafjk
|
||||||
|
@ -2,24 +2,22 @@
|
|||||||
server:
|
server:
|
||||||
port: 80
|
port: 80
|
||||||
|
|
||||||
# sa-token配置
|
# sa-token 配置
|
||||||
sa-token:
|
sa-token:
|
||||||
# token名称 (同时也是cookie名称)
|
# token 名称 (同时也是 cookie 名称)
|
||||||
token-name: satoken
|
token-name: satoken
|
||||||
# token有效期,单位s 默认30天, -1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: -1
|
||||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
is-concurrent: true
|
is-concurrent: true
|
||||||
# 禁止写入cookie
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
is-read-cookie: false
|
is-share: true
|
||||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
is-share: false
|
|
||||||
# token风格
|
|
||||||
token-style: uuid
|
token-style: uuid
|
||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
is-log: false
|
is-log: true
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
# redis配置
|
# redis配置
|
||||||
|
@ -159,8 +159,8 @@ public class TestController {
|
|||||||
public AjaxJson atCheck() {
|
public AjaxJson atCheck() {
|
||||||
System.out.println("======================= 进入方法,测试注解鉴权接口 ========================= ");
|
System.out.println("======================= 进入方法,测试注解鉴权接口 ========================= ");
|
||||||
System.out.println("只有通过注解鉴权,才能进入此方法");
|
System.out.println("只有通过注解鉴权,才能进入此方法");
|
||||||
// StpUtil.checkActivityTimeout();
|
// StpUtil.checkActiveTimeout();
|
||||||
// StpUtil.updateLastActivityToNow();
|
// StpUtil.updateLastActiveToNow();
|
||||||
return AjaxJson.getSuccess();
|
return AjaxJson.getSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,8 +174,8 @@ public class TestController {
|
|||||||
// [活动时间] 续签: http://localhost:8081/test/rene
|
// [活动时间] 续签: http://localhost:8081/test/rene
|
||||||
@Mapping("rene")
|
@Mapping("rene")
|
||||||
public AjaxJson rene() {
|
public AjaxJson rene() {
|
||||||
StpUtil.checkActivityTimeout();
|
StpUtil.checkActiveTimeout();
|
||||||
StpUtil.updateLastActivityToNow();
|
StpUtil.updateLastActiveToNow();
|
||||||
return AjaxJson.getSuccess("续签成功");
|
return AjaxJson.getSuccess("续签成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,19 +2,19 @@
|
|||||||
server:
|
server:
|
||||||
port: 8081
|
port: 8081
|
||||||
|
|
||||||
# sa-token配置
|
# sa-token 配置
|
||||||
sa-token:
|
sa-token:
|
||||||
# token名称 (同时也是cookie名称)
|
# token 名称 (同时也是 cookie 名称)
|
||||||
token-name: satoken
|
token-name: satoken
|
||||||
# token有效期,单位s 默认30天, -1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: -1
|
||||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
allow-concurrent-login: true
|
is-concurrent: true
|
||||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
is-share: true
|
is-share: true
|
||||||
# token风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
token-style: uuid
|
token-style: uuid
|
||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
is-log: true
|
is-log: true
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
# 端口
|
# 端口
|
||||||
server:
|
server:
|
||||||
port: 8081
|
port: 8081
|
||||||
|
|
||||||
# sa-token配置
|
# sa-token 配置
|
||||||
sa-token:
|
sa-token:
|
||||||
# token名称 (同时也是cookie名称)
|
# token 名称 (同时也是 cookie 名称)
|
||||||
token-name: satoken
|
token-name: satoken
|
||||||
# token有效期,单位s 默认30天, -1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: -1
|
||||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
is-concurrent: true
|
is-concurrent: true
|
||||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
is-share: true
|
is-share: true
|
||||||
# token风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
token-style: uuid
|
token-style: uuid
|
||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
is-log: true
|
is-log: true
|
||||||
|
@ -2,21 +2,21 @@
|
|||||||
server:
|
server:
|
||||||
port: 8081
|
port: 8081
|
||||||
|
|
||||||
# sa-token配置
|
# sa-token 配置
|
||||||
sa-token:
|
sa-token:
|
||||||
# token名称 (同时也是cookie名称)
|
# token 名称 (同时也是 cookie 名称)
|
||||||
token-name: satoken
|
token-name: satoken
|
||||||
# token有效期,单位s 默认30天, -1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: -1
|
||||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
is-concurrent: true
|
is-concurrent: true
|
||||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
is-share: true
|
is-share: true
|
||||||
# token风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
token-style: uuid
|
token-style: uuid
|
||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
is-log: true
|
is-log: true
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
|
@ -160,8 +160,8 @@ public class TestController {
|
|||||||
public AjaxJson atCheck() {
|
public AjaxJson atCheck() {
|
||||||
System.out.println("======================= 进入方法,测试注解鉴权接口 ========================= ");
|
System.out.println("======================= 进入方法,测试注解鉴权接口 ========================= ");
|
||||||
System.out.println("只有通过注解鉴权,才能进入此方法");
|
System.out.println("只有通过注解鉴权,才能进入此方法");
|
||||||
// StpUtil.checkActivityTimeout();
|
// StpUtil.checkActiveTimeout();
|
||||||
// StpUtil.updateLastActivityToNow();
|
// StpUtil.updateLastActiveToNow();
|
||||||
return AjaxJson.getSuccess();
|
return AjaxJson.getSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,8 +175,8 @@ public class TestController {
|
|||||||
// [活动时间] 续签: http://localhost:8081/test/rene
|
// [活动时间] 续签: http://localhost:8081/test/rene
|
||||||
@RequestMapping("rene")
|
@RequestMapping("rene")
|
||||||
public AjaxJson rene() {
|
public AjaxJson rene() {
|
||||||
StpUtil.checkActivityTimeout();
|
StpUtil.checkActiveTimeout();
|
||||||
StpUtil.updateLastActivityToNow();
|
StpUtil.updateLastActiveToNow();
|
||||||
return AjaxJson.getSuccess("续签成功");
|
return AjaxJson.getSuccess("续签成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
# 端口
|
# 端口
|
||||||
server:
|
server:
|
||||||
port: 8081
|
port: 8081
|
||||||
|
|
||||||
# sa-token配置
|
# sa-token 配置
|
||||||
sa-token:
|
sa-token:
|
||||||
# token名称 (同时也是cookie名称)
|
# token 名称 (同时也是 cookie 名称)
|
||||||
token-name: satoken
|
token-name: satoken
|
||||||
# token有效期,单位s 默认30天, -1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: -1
|
||||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
is-concurrent: true
|
is-concurrent: true
|
||||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
is-share: true
|
is-share: true
|
||||||
# token风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
token-style: uuid
|
token-style: uuid
|
||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
is-log: false
|
is-log: true
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
# redis配置
|
# redis配置
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
# 端口
|
# 端口
|
||||||
server:
|
server:
|
||||||
port: 8081
|
port: 8081
|
||||||
|
|
||||||
# sa-token配置
|
# sa-token 配置
|
||||||
sa-token:
|
sa-token:
|
||||||
# token名称 (同时也是cookie名称)
|
# token 名称 (同时也是 cookie 名称)
|
||||||
token-name: satoken
|
token-name: satoken
|
||||||
# token有效期,单位s 默认30天, -1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: -1
|
||||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
is-concurrent: true
|
is-concurrent: true
|
||||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
is-share: true
|
is-share: true
|
||||||
# token风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
token-style: uuid
|
token-style: uuid
|
||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
is-log: true
|
is-log: true
|
||||||
|
@ -7,17 +7,15 @@ import cn.dev33.satoken.session.SaSession;
|
|||||||
import cn.dev33.satoken.stp.SaLoginModel;
|
import cn.dev33.satoken.stp.SaLoginModel;
|
||||||
import cn.dev33.satoken.stp.SaTokenInfo;
|
import cn.dev33.satoken.stp.SaTokenInfo;
|
||||||
import cn.dev33.satoken.stp.StpLogic;
|
import cn.dev33.satoken.stp.StpLogic;
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sa-Token 权限认证工具类 (User版)
|
* Sa-Token 权限认证工具类 (User 版)
|
||||||
*
|
*
|
||||||
* @author click33
|
* @author click33
|
||||||
* @since <= 1.34.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
@Component
|
|
||||||
public class StpUserUtil {
|
public class StpUserUtil {
|
||||||
|
|
||||||
private StpUserUtil() {}
|
private StpUserUtil() {}
|
||||||
@ -25,7 +23,7 @@ public class StpUserUtil {
|
|||||||
/**
|
/**
|
||||||
* 多账号体系下的类型标识
|
* 多账号体系下的类型标识
|
||||||
*/
|
*/
|
||||||
public static final String TYPE = "user";
|
public static final String TYPE = "login";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 底层使用的 StpLogic 对象
|
* 底层使用的 StpLogic 对象
|
||||||
@ -483,24 +481,24 @@ public class StpUserUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------- Activity-Timeout token 最低活跃度 验证相关 -------------------
|
// ------------------- Active-Timeout token 最低活跃度 验证相关 -------------------
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查当前 token 是否已被冻结,如果是则抛出异常
|
|
||||||
*/
|
|
||||||
public static void checkActivityTimeout() {
|
|
||||||
stpLogic.checkActivityTimeout();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 续签当前 token:(将 [最后操作时间] 更新为当前时间戳)
|
* 续签当前 token:(将 [最后操作时间] 更新为当前时间戳)
|
||||||
* <h2>
|
* <h2>
|
||||||
* 请注意: 即使 token 已被冻结 也可续签成功,
|
* 请注意: 即使 token 已被冻结 也可续签成功,
|
||||||
* 如果此场景下需要提示续签失败,可在此之前调用 checkActivityTimeout() 强制检查是否冻结即可
|
* 如果此场景下需要提示续签失败,可在此之前调用 checkActiveTimeout() 强制检查是否冻结即可
|
||||||
* </h2>
|
* </h2>
|
||||||
*/
|
*/
|
||||||
public static void updateLastActivityToNow() {
|
public static void updateLastActiveToNow() {
|
||||||
stpLogic.updateLastActivityToNow();
|
stpLogic.updateLastActiveToNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查当前 token 是否已被冻结,如果是则抛出异常
|
||||||
|
*/
|
||||||
|
public static void checkActiveTimeout() {
|
||||||
|
stpLogic.checkActiveTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -548,8 +546,8 @@ public class StpUserUtil {
|
|||||||
*
|
*
|
||||||
* @return /
|
* @return /
|
||||||
*/
|
*/
|
||||||
public static long getTokenActivityTimeout() {
|
public static long getTokenActiveTimeout() {
|
||||||
return stpLogic.getTokenActivityTimeout();
|
return stpLogic.getTokenActiveTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
package com.pj.test;
|
package com.pj.test;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.SaLoginConfig;
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
import cn.dev33.satoken.util.SaResult;
|
import cn.dev33.satoken.util.SaResult;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 测试专用Controller
|
* 测试专用Controller
|
||||||
* @author click33
|
* @author click33
|
||||||
@ -18,14 +22,15 @@ public class TestController {
|
|||||||
// 测试登录 ---- http://localhost:8081/test/login
|
// 测试登录 ---- http://localhost:8081/test/login
|
||||||
@RequestMapping("login")
|
@RequestMapping("login")
|
||||||
public SaResult login(@RequestParam(defaultValue = "10001") long id) {
|
public SaResult login(@RequestParam(defaultValue = "10001") long id) {
|
||||||
StpUtil.login(id);
|
StpUtil.login(id, SaLoginConfig.setActiveTimeout(20));
|
||||||
return SaResult.ok("登录成功");
|
return SaResult.ok("登录成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 测试 浏览器访问: http://localhost:8081/test/test
|
// 测试 浏览器访问: http://localhost:8081/test/test
|
||||||
@RequestMapping("test")
|
@RequestMapping("test")
|
||||||
public SaResult test() {
|
public SaResult test() {
|
||||||
System.out.println("------------进来了");
|
System.out.println("------------进来了 " + SaFoxUtil.formatDate(new Date()));
|
||||||
|
StpUtil.checkLogin();
|
||||||
// 返回
|
// 返回
|
||||||
return SaResult.data(null);
|
return SaResult.data(null);
|
||||||
}
|
}
|
||||||
|
@ -4,17 +4,17 @@ server:
|
|||||||
|
|
||||||
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
|
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
|
||||||
sa-token:
|
sa-token:
|
||||||
# token名称 (同时也是cookie名称)
|
# token 名称 (同时也是 cookie 名称)
|
||||||
token-name: satoken
|
token-name: satoken
|
||||||
# token有效期,单位s 默认30天, -1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: 100000
|
||||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
is-concurrent: true
|
is-concurrent: true
|
||||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
is-share: true
|
is-share: true
|
||||||
# token风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
token-style: uuid
|
token-style: uuid
|
||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
is-log: true
|
is-log: true
|
||||||
|
@ -2,21 +2,21 @@
|
|||||||
server:
|
server:
|
||||||
port: 8081
|
port: 8081
|
||||||
|
|
||||||
# sa-token配置
|
# sa-token 配置
|
||||||
sa-token:
|
sa-token:
|
||||||
# token名称 (同时也是cookie名称)
|
# token 名称 (同时也是 cookie 名称)
|
||||||
token-name: satoken
|
token-name: satoken
|
||||||
# token有效期,单位s 默认30天, -1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: -1
|
||||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
is-concurrent: true
|
is-concurrent: true
|
||||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
is-share: true
|
is-share: true
|
||||||
# token风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
token-style: uuid
|
token-style: uuid
|
||||||
# 日志
|
# 是否输出操作日志
|
||||||
is-log: true
|
is-log: true
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
|
@ -2,21 +2,21 @@
|
|||||||
server:
|
server:
|
||||||
port: 8081
|
port: 8081
|
||||||
|
|
||||||
# sa-token配置
|
# sa-token 配置
|
||||||
sa-token:
|
sa-token:
|
||||||
# token名称 (同时也是cookie名称)
|
# token 名称 (同时也是 cookie 名称)
|
||||||
token-name: satoken
|
token-name: satoken
|
||||||
# token有效期,单位s 默认30天, -1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: -1
|
||||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
is-concurrent: true
|
is-concurrent: true
|
||||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
is-share: true
|
is-share: true
|
||||||
# token风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
token-style: uuid
|
token-style: uuid
|
||||||
# 日志
|
# 是否输出操作日志
|
||||||
is-log: true
|
is-log: true
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
# 端口
|
# 端口
|
||||||
server:
|
server:
|
||||||
port: 8081
|
port: 8081
|
||||||
|
|
||||||
# sa-token配置
|
# sa-token 配置
|
||||||
sa-token:
|
sa-token:
|
||||||
# token名称 (同时也是cookie名称)
|
# token 名称 (同时也是 cookie 名称)
|
||||||
token-name: satoken
|
token-name: satoken
|
||||||
# token有效期,单位s 默认30天, -1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: -1
|
||||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
is-concurrent: true
|
is-concurrent: true
|
||||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
is-share: true
|
is-share: true
|
||||||
# token风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
token-style: uuid
|
token-style: uuid
|
||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
is-log: false
|
is-log: true
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
# redis配置
|
# redis配置
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
# 端口
|
# 端口
|
||||||
server:
|
server:
|
||||||
port: 8081
|
port: 8081
|
||||||
|
|
||||||
# sa-token配置
|
# sa-token 配置
|
||||||
sa-token:
|
sa-token:
|
||||||
# token名称 (同时也是cookie名称)
|
# token 名称 (同时也是 cookie 名称)
|
||||||
token-name: satoken
|
token-name: satoken
|
||||||
# token有效期,单位s 默认30天, -1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: -1
|
||||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
is-concurrent: true
|
is-concurrent: true
|
||||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
is-share: true
|
is-share: true
|
||||||
# token风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
token-style: uuid
|
token-style: uuid
|
||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
is-log: false
|
is-log: true
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
# redis配置
|
# redis配置
|
||||||
|
@ -90,12 +90,12 @@ StpUtil.getSessionBySessionId("xxxx-xxxx-xxxx"); // 获取指定key的Session,
|
|||||||
|
|
||||||
### 6、Token有效期相关
|
### 6、Token有效期相关
|
||||||
``` java
|
``` java
|
||||||
// 临时有效期
|
// Token 最低活跃频率
|
||||||
StpUtil.getTokenActivityTimeout(); // 获取当前 token [临时过期] 剩余有效时间 (单位: 秒)
|
StpUtil.getTokenActiveTimeout(); // 获取当前 token 距离被冻结还剩多少时间 (单位: 秒)
|
||||||
StpUtil.checkActivityTimeout(); // 检查当前token 是否已经[临时过期],如果已经过期则抛出异常
|
StpUtil.checkActiveTimeout(); // 检查当前token 是否已经被冻结,如果是则抛出异常
|
||||||
StpUtil.updateLastActivityToNow(); // 续签当前token:(将 [最后操作时间] 更新为当前时间戳)
|
StpUtil.updateLastActiveToNow(); // 续签当前token:(将 [最后操作时间] 更新为当前时间戳)
|
||||||
|
|
||||||
// 长久有效期
|
// Token 有效期
|
||||||
StpUtil.getTokenTimeout(); // 获取当前登录者的 token 剩余有效时间 (单位: 秒)
|
StpUtil.getTokenTimeout(); // 获取当前登录者的 token 剩余有效时间 (单位: 秒)
|
||||||
StpUtil.getSessionTimeout(); // 获取当前登录者的 Account-Session 剩余有效时间 (单位: 秒)
|
StpUtil.getSessionTimeout(); // 获取当前登录者的 Account-Session 剩余有效时间 (单位: 秒)
|
||||||
StpUtil.getTokenSessionTimeout(); // 获取当前 Token-Session 剩余有效时间 (单位: 秒)
|
StpUtil.getTokenSessionTimeout(); // 获取当前 Token-Session 剩余有效时间 (单位: 秒)
|
||||||
|
@ -79,7 +79,7 @@ SaToken 中的所有异常都是继承于 `SaTokenException` 的,也就是说
|
|||||||
| 11013 | Token已过期 |
|
| 11013 | Token已过期 |
|
||||||
| 11014 | Token已被顶下线 |
|
| 11014 | Token已被顶下线 |
|
||||||
| 11015 | Token已被踢下线 |
|
| 11015 | Token已被踢下线 |
|
||||||
| 11016 | Token已临时过期 |
|
| 11016 | Token已被冻结 |
|
||||||
| 11031 | 在未集成 sa-token-jwt 插件时调用 getExtra() 抛出异常 |
|
| 11031 | 在未集成 sa-token-jwt 插件时调用 getExtra() 抛出异常 |
|
||||||
| 11041 | 缺少指定的角色 |
|
| 11041 | 缺少指定的角色 |
|
||||||
| 11051 | 缺少指定的权限 |
|
| 11051 | 缺少指定的权限 |
|
||||||
|
@ -15,7 +15,7 @@ token信息Model: 用来描述一个token的常用参数
|
|||||||
"tokenTimeout": 2591977, // token剩余有效期 (单位: 秒)
|
"tokenTimeout": 2591977, // token剩余有效期 (单位: 秒)
|
||||||
"sessionTimeout": 2591977, // Account-Session剩余有效时间 (单位: 秒)
|
"sessionTimeout": 2591977, // Account-Session剩余有效时间 (单位: 秒)
|
||||||
"tokenSessionTimeout": -2, // Token-Session剩余有效时间 (单位: 秒) (-2表示系统中不存在这个缓存)
|
"tokenSessionTimeout": -2, // Token-Session剩余有效时间 (单位: 秒) (-2表示系统中不存在这个缓存)
|
||||||
"tokenActivityTimeout": -1, // token剩余无操作有效时间 (单位: 秒)
|
"tokenActiveTimeout": -1, // token 距离被冻结还剩的时间 (单位: 秒)
|
||||||
"loginDevice": "default-device" // 登录设备类型
|
"loginDevice": "default-device" // 登录设备类型
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<!-- 本篇介绍Token有效期的详细用法 -->
|
<!-- 本篇介绍Token有效期的详细用法 -->
|
||||||
|
|
||||||
Sa-Token 提供两种 Token 自动过期策略,分别是 `timeout` 与 `activity-timeout`,配置方法如下:
|
Sa-Token 提供两种 Token 自动过期策略,分别是 `timeout` 与 `active-timeout`,配置方法如下:
|
||||||
|
|
||||||
<!---------------------------- tabs:start ---------------------------->
|
<!---------------------------- tabs:start ---------------------------->
|
||||||
<!------------- tab:yaml 风格 ------------->
|
<!------------- tab:yaml 风格 ------------->
|
||||||
@ -11,14 +11,14 @@ sa-token:
|
|||||||
# token 有效期(单位:秒),默认30天,-1代表永不过期
|
# token 有效期(单位:秒),默认30天,-1代表永不过期
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: -1
|
||||||
```
|
```
|
||||||
<!------------- tab:properties 风格 ------------->
|
<!------------- tab:properties 风格 ------------->
|
||||||
``` properties
|
``` properties
|
||||||
# token 有效期(单位:秒),默认30天,-1代表永不过期
|
# token 有效期(单位:秒),默认30天,-1代表永不过期
|
||||||
sa-token.timeout=2592000
|
sa-token.timeout=2592000
|
||||||
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
sa-token.activity-timeout=-1
|
sa-token.active-timeout=-1
|
||||||
```
|
```
|
||||||
<!---------------------------- tabs:end ---------------------------->
|
<!---------------------------- tabs:end ---------------------------->
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ sa-token.activity-timeout=-1
|
|||||||
> 2. 银行为你颁发一张储蓄卡(系统为你颁发一个Token),以后每次存取钱都要带上这张卡(后续每次访问系统都要提交 Token)。
|
> 2. 银行为你颁发一张储蓄卡(系统为你颁发一个Token),以后每次存取钱都要带上这张卡(后续每次访问系统都要提交 Token)。
|
||||||
> 3. 银行为这张卡设定两个过期时间:
|
> 3. 银行为这张卡设定两个过期时间:
|
||||||
> - 第一个是 `timeout`,代表这张卡的长久有效期,就是指这张卡最长能用多久,假设 `timeout=3年`,那么3年后此卡将被银行删除,想要继续来银行办理业务必须重新办卡(Token 过期后想要访问系统必须重新登录)。
|
> - 第一个是 `timeout`,代表这张卡的长久有效期,就是指这张卡最长能用多久,假设 `timeout=3年`,那么3年后此卡将被银行删除,想要继续来银行办理业务必须重新办卡(Token 过期后想要访问系统必须重新登录)。
|
||||||
> - 第二个就是 `activity-timeout`,代表这张卡的最低活跃频率限制,就是指这张卡必须每隔多久来银行一次,假设 `activity-timeout=1月` ,你如果超过1月不来办一次业务,银行就将你的卡冻结,列为长期不动户(Token 长期不访问系统,被冻结,但不会被删除)。
|
> - 第二个就是 `active-timeout`,代表这张卡的最低活跃频率限制,就是指这张卡必须每隔多久来银行一次,假设 `active-timeout=1月` ,你如果超过1月不来办一次业务,银行就将你的卡冻结,列为长期不动户(Token 长期不访问系统,被冻结,但不会被删除)。
|
||||||
> 4. 两个过期策略可以单独配置,也可以同时配置,只要有其中一个有效期超出了范围,这张卡就会变得不可用(两个有效期只要有一个过期了,Token就无法成功访问系统了)。
|
> 4. 两个过期策略可以单独配置,也可以同时配置,只要有其中一个有效期超出了范围,这张卡就会变得不可用(两个有效期只要有一个过期了,Token就无法成功访问系统了)。
|
||||||
|
|
||||||
下面是对两个过期策略的详细解释:
|
下面是对两个过期策略的详细解释:
|
||||||
@ -40,33 +40,33 @@ sa-token.activity-timeout=-1
|
|||||||
3. `timeout`的值配置为-1后,代表永久有效,不会过期。
|
3. `timeout`的值配置为-1后,代表永久有效,不会过期。
|
||||||
|
|
||||||
|
|
||||||
### activity-timeout
|
### active-timeout
|
||||||
1. `activity-timeout`代表最低活跃频率,单位/秒,例如将其配置为 1800 (30分钟),代表用户如果30分钟无操作,则此Token会立即过期(被冻结,但不会删除掉)。
|
1. `active-timeout`代表最低活跃频率,单位/秒,例如将其配置为 1800 (30分钟),代表用户如果30分钟无操作,则此Token会立即过期(被冻结,但不会删除掉)。
|
||||||
2. 如果在30分钟内用户有操作,则会再次续签30分钟,用户如果一直操作则会一直续签,直到连续30分钟无操作,Token才会过期。
|
2. 如果在30分钟内用户有操作,则会再次续签30分钟,用户如果一直操作则会一直续签,直到连续30分钟无操作,Token才会过期。
|
||||||
3. `activity-timeout`的值配置为-1后,代表永久有效,不会过期,此时也无需频繁续签。
|
3. `active-timeout`的值配置为-1后,代表永久有效,不会过期,此时也无需频繁续签。
|
||||||
|
|
||||||
|
|
||||||
### 关于activity-timeout的续签
|
### 关于active-timeout的续签
|
||||||
如果`activity-timeout`配置了大于零的值,Sa-Token 会在登录时开始计时,在每次直接或间接调用`getLoginId()`时进行一次冻结检查与续签操作。
|
如果`active-timeout`配置了大于零的值,Sa-Token 会在登录时开始计时,在每次直接或间接调用`getLoginId()`时进行一次冻结检查与续签操作。
|
||||||
此时会有两种情况:
|
此时会有两种情况:
|
||||||
1. 一种是会话无操作时间太长,Token已经被冻结,此时框架会抛出`NotLoginException`异常(场景值=-3),
|
1. 一种是会话无操作时间太长,Token已经被冻结,此时框架会抛出`NotLoginException`异常(场景值=-3),
|
||||||
2. 另一种则是会话在`activity-timeout`有效期内通过检查,此时Token可以成功续签
|
2. 另一种则是会话在`active-timeout`有效期内通过检查,此时Token可以成功续签
|
||||||
|
|
||||||
|
|
||||||
### 我可以手动续签 activity-timeout 吗?
|
### 我可以手动续签 active-timeout 吗?
|
||||||
**可以!**
|
**可以!**
|
||||||
如果框架的自动续签算法无法满足您的业务需求,你可以进行手动续签,Sa-Token 提供两个API供你操作:
|
如果框架的自动续签算法无法满足您的业务需求,你可以进行手动续签,Sa-Token 提供两个API供你操作:
|
||||||
1. `StpUtil.checkActivityTimeout()`: 检查当前Token 是否已经被冻结,如果是则抛出异常
|
1. `StpUtil.checkActiveTimeout()`: 检查当前Token 是否已经被冻结,如果是则抛出异常
|
||||||
2. `StpUtil.updateLastActivityToNow()`: 续签当前Token:(将 [最后操作时间] 更新为当前时间戳)
|
2. `StpUtil.updateLastActiveToNow()`: 续签当前Token:(将 [最后操作时间] 更新为当前时间戳)
|
||||||
|
|
||||||
注意:在手动续签时,即使 Token 已经被冻结也可续签成功(解冻),如果此场景下需要提示续签失败,可采用先检查再续签的形式保证Token有效性
|
注意:在手动续签时,即使 Token 已经被冻结也可续签成功(解冻),如果此场景下需要提示续签失败,可采用先检查再续签的形式保证Token有效性
|
||||||
|
|
||||||
例如以下代码:
|
例如以下代码:
|
||||||
``` java
|
``` java
|
||||||
// 先检查是否已被冻结
|
// 先检查是否已被冻结
|
||||||
StpUtil.checkActivityTimeout();
|
StpUtil.checkActiveTimeout();
|
||||||
// 检查通过后继续续签
|
// 检查通过后继续续签
|
||||||
StpUtil.updateLastActivityToNow();
|
StpUtil.updateLastActiveToNow();
|
||||||
```
|
```
|
||||||
|
|
||||||
同时,你还可以关闭框架的自动续签(在配置文件中配置 `autoRenew=false` ),此时续签操作完全由开发者控制,框架不再自动进行任何续签操作
|
同时,你还可以关闭框架的自动续签(在配置文件中配置 `autoRenew=false` ),此时续签操作完全由开发者控制,框架不再自动进行任何续签操作
|
||||||
@ -75,16 +75,16 @@ StpUtil.updateLastActivityToNow();
|
|||||||
|
|
||||||
``` java
|
``` java
|
||||||
// 为指定 Token 续签
|
// 为指定 Token 续签
|
||||||
StpUtil.stpLogic.updateLastActivityToNow(tokenValue);
|
StpUtil.stpLogic.updateLastActiveToNow(tokenValue);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### timeout 与 activity-timeout 可以同时使用吗?
|
### timeout 与 active-timeout 可以同时使用吗?
|
||||||
**可以同时使用!**
|
**可以同时使用!**
|
||||||
两者的认证逻辑彼此独立,互不干扰,可以同时使用。
|
两者的认证逻辑彼此独立,互不干扰,可以同时使用。
|
||||||
|
|
||||||
|
|
||||||
### StpUtil 类中哪些公开方法支持临时有效期自动续签 activity-timeout?
|
### StpUtil 类中哪些公开方法支持自动续签 active-timeout?
|
||||||
> 直接或间接获取了当前用户id的方法 (间接调用过 StpLogic.getLoginId() 方法)
|
> 直接或间接获取了当前用户id的方法 (间接调用过 StpLogic.getLoginId() 方法)
|
||||||
|
|
||||||
| 包括但不限于这些: |
|
| 包括但不限于这些: |
|
||||||
|
@ -73,18 +73,20 @@ SaFoxUtil.toList(... strs); // String 数组转集合
|
|||||||
|
|
||||||
1、首先在项目根目录,创建一个配置文件:`sa-token.properties`
|
1、首先在项目根目录,创建一个配置文件:`sa-token.properties`
|
||||||
|
|
||||||
``` java
|
``` properties
|
||||||
# token名称 (同时也是cookie名称)
|
# token 名称 (同时也是 cookie 名称)
|
||||||
tokenName=satoken
|
tokenName=satoken
|
||||||
# token有效期,单位s 默认30天, -1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout=2592000
|
timeout=2592000
|
||||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activityTimeout=-1
|
activeTimeout=-1
|
||||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) =-1
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
isConcurrent=true
|
isConcurrent=true
|
||||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
isShare=true
|
isShare=true
|
||||||
# token风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
|
tokenStyle=uuid
|
||||||
|
# 是否输出操作日志
|
||||||
isLog=false
|
isLog=false
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ Sa-Token 的部分 API 只能在 Web 上下文中才能调用,例如:`StpUti
|
|||||||
- 可能9:可能是多账号鉴权的关系,在多账号模式下,如果是 `StpUserUtil.login()` 颁发的token,你从 `StpUtil.checkLogin()` 进行校验,永远都是无效token,因为账号体系没对上。
|
- 可能9:可能是多账号鉴权的关系,在多账号模式下,如果是 `StpUserUtil.login()` 颁发的token,你从 `StpUtil.checkLogin()` 进行校验,永远都是无效token,因为账号体系没对上。
|
||||||
|
|
||||||
**如果是:Token已过期:6ad93254-b286-4ec9-9997-4430b0341ca0**
|
**如果是: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超时了)。
|
- 可能2:集成jwt,而且使用的是 Mixin 或 Stateless 模式,而且token过期了(timeout超时了)。
|
||||||
|
|
||||||
**如果是:Token已被顶下线:6ad93254-b286-4ec9-9997-4430b0341ca0**
|
**如果是:Token已被顶下线:6ad93254-b286-4ec9-9997-4430b0341ca0**
|
||||||
|
@ -18,7 +18,7 @@ Sa-Token 无意发明任何晦涩概念提升逼格,但在处理 issue 、Q群
|
|||||||
|
|
||||||
#### 两种过期时间:
|
#### 两种过期时间:
|
||||||
- timeout:会话 Token 的长久有效期。
|
- timeout:会话 Token 的长久有效期。
|
||||||
- activity-timeout:会话的临时有效期。
|
- active-timeout:会话 Token 的最低活跃频率。
|
||||||
|
|
||||||
两者的差别详见:[Token有效期详解](/fun/token-timeout)
|
两者的差别详见:[Token有效期详解](/fun/token-timeout)
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbklkIjoiMTAwMDEiLCJybiI6IjZYYzgySzB
|
|||||||
| 角色认证 | 支持 | 支持 | 支持 |
|
| 角色认证 | 支持 | 支持 | 支持 |
|
||||||
| 权限认证 | 支持 | 支持 | 支持 |
|
| 权限认证 | 支持 | 支持 | 支持 |
|
||||||
| timeout 有效期 | 支持 | 支持 | 支持 |
|
| timeout 有效期 | 支持 | 支持 | 支持 |
|
||||||
| activity-timeout 有效期 | 支持 | 支持 | 不支持 |
|
| active-timeout 有效期 | 支持 | 支持 | 不支持 |
|
||||||
| id反查Token | 支持 | 支持 | 不支持 |
|
| id反查Token | 支持 | 支持 | 不支持 |
|
||||||
| 会话管理 | 支持 | 部分支持 | 不支持 |
|
| 会话管理 | 支持 | 部分支持 | 不支持 |
|
||||||
| 注解鉴权 | 支持 | 支持 | 支持 |
|
| 注解鉴权 | 支持 | 支持 | 支持 |
|
||||||
|
@ -57,18 +57,18 @@ server:
|
|||||||
sa-token:
|
sa-token:
|
||||||
# token 名称(同时也是 cookie 名称)
|
# token 名称(同时也是 cookie 名称)
|
||||||
token-name: satoken
|
token-name: satoken
|
||||||
# token 有效期(单位:秒),默认30天,-1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: -1
|
||||||
# 是否允许同一账号多地同时登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
is-concurrent: true
|
is-concurrent: true
|
||||||
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token,为 false 时每次登录新建一个 token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
is-share: true
|
is-share: true
|
||||||
# token 风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
token-style: uuid
|
token-style: uuid
|
||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
is-log: false
|
is-log: true
|
||||||
```
|
```
|
||||||
|
|
||||||
<!------------- tab:application.properties 风格 ------------->
|
<!------------- tab:application.properties 风格 ------------->
|
||||||
@ -78,20 +78,20 @@ server.port=8081
|
|||||||
|
|
||||||
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
|
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
|
||||||
|
|
||||||
# token名称(同时也是 cookie 名称)
|
# token 名称(同时也是 cookie 名称)
|
||||||
sa-token.token-name=satoken
|
sa-token.token-name=satoken
|
||||||
# token 有效期(单位:秒),默认30天,-1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
sa-token.timeout=2592000
|
sa-token.timeout=2592000
|
||||||
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
sa-token.activity-timeout=-1
|
sa-token.active-timeout=-1
|
||||||
# 是否允许同一账号多地同时登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
sa-token.is-concurrent=true
|
sa-token.is-concurrent=true
|
||||||
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token,为 false 时每次登录新建一个 token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
sa-token.is-share=true
|
sa-token.is-share=true
|
||||||
# token 风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
sa-token.token-style=uuid
|
sa-token.token-style=uuid
|
||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
sa-token.is-log=false
|
sa-token.is-log=true
|
||||||
```
|
```
|
||||||
|
|
||||||
<!---------------------------- tabs:end ---------------------------->
|
<!---------------------------- tabs:end ---------------------------->
|
||||||
|
@ -68,18 +68,18 @@ server:
|
|||||||
sa-token:
|
sa-token:
|
||||||
# token 名称(同时也是 cookie 名称)
|
# token 名称(同时也是 cookie 名称)
|
||||||
token-name: satoken
|
token-name: satoken
|
||||||
# token 有效期(单位:秒),默认30天,-1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: -1
|
||||||
# 是否允许同一账号多地同时登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
is-concurrent: true
|
is-concurrent: true
|
||||||
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token,为 false 时每次登录新建一个 token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
is-share: true
|
is-share: true
|
||||||
# token 风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
token-style: uuid
|
token-style: uuid
|
||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
is-log: false
|
is-log: true
|
||||||
```
|
```
|
||||||
|
|
||||||
<!------------- tab:app.properties 风格 ------------->
|
<!------------- tab:app.properties 风格 ------------->
|
||||||
@ -89,20 +89,20 @@ server.port=8081
|
|||||||
|
|
||||||
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
|
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
|
||||||
|
|
||||||
# token名称(同时也是 cookie 名称)
|
# token 名称(同时也是 cookie 名称)
|
||||||
sa-token.token-name=satoken
|
sa-token.token-name=satoken
|
||||||
# token 有效期(单位:秒),默认30天,-1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
sa-token.timeout=2592000
|
sa-token.timeout=2592000
|
||||||
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
sa-token.activity-timeout=-1
|
sa-token.active-timeout=-1
|
||||||
# 是否允许同一账号多地同时登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
sa-token.is-concurrent=true
|
sa-token.is-concurrent=true
|
||||||
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token,为 false 时每次登录新建一个 token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
sa-token.is-share=true
|
sa-token.is-share=true
|
||||||
# token 风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
sa-token.token-style=uuid
|
sa-token.token-style=uuid
|
||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
sa-token.is-log=false
|
sa-token.is-log=true
|
||||||
```
|
```
|
||||||
|
|
||||||
<!---------------------------- tabs:end ---------------------------->
|
<!---------------------------- tabs:end ---------------------------->
|
||||||
|
@ -14,38 +14,38 @@
|
|||||||
sa-token:
|
sa-token:
|
||||||
# token 名称(同时也是 cookie 名称)
|
# token 名称(同时也是 cookie 名称)
|
||||||
token-name: satoken
|
token-name: satoken
|
||||||
# token 有效期(单位:秒),默认30天,-1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: -1
|
||||||
# 是否允许同一账号多地同时登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
is-concurrent: true
|
is-concurrent: true
|
||||||
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token,为 false 时每次登录新建一个 token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
is-share: true
|
is-share: true
|
||||||
# token 风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
token-style: uuid
|
token-style: uuid
|
||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
is-log: false
|
is-log: true
|
||||||
```
|
```
|
||||||
|
|
||||||
<!------------- tab:properties 风格 ------------->
|
<!------------- tab:properties 风格 ------------->
|
||||||
``` properties
|
``` properties
|
||||||
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
|
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
|
||||||
|
|
||||||
# token名称(同时也是 cookie 名称)
|
# token 名称(同时也是 cookie 名称)
|
||||||
sa-token.token-name=satoken
|
sa-token.token-name=satoken
|
||||||
# token 有效期(单位:秒),默认30天,-1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
sa-token.timeout=2592000
|
sa-token.timeout=2592000
|
||||||
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
sa-token.activity-timeout=-1
|
sa-token.active-timeout=-1
|
||||||
# 是否允许同一账号多地同时登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
sa-token.is-concurrent=true
|
sa-token.is-concurrent=true
|
||||||
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token,为 false 时每次登录新建一个 token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
sa-token.is-share=true
|
sa-token.is-share=true
|
||||||
# token 风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
sa-token.token-style=uuid
|
sa-token.token-style=uuid
|
||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
sa-token.is-log=false
|
sa-token.is-log=true
|
||||||
```
|
```
|
||||||
|
|
||||||
<!---------------------------- tabs:end ---------------------------->
|
<!---------------------------- tabs:end ---------------------------->
|
||||||
@ -70,7 +70,7 @@ public class SaTokenConfigure {
|
|||||||
SaTokenConfig config = new SaTokenConfig();
|
SaTokenConfig config = new SaTokenConfig();
|
||||||
config.setTokenName("satoken"); // token 名称(同时也是 cookie 名称)
|
config.setTokenName("satoken"); // token 名称(同时也是 cookie 名称)
|
||||||
config.setTimeout(30 * 24 * 60 * 60); // token 有效期(单位:秒),默认30天,-1代表永不过期
|
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.setIsConcurrent(true); // 是否允许同一账号多地同时登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录)
|
||||||
config.setIsShare(true); // 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token,为 false 时每次登录新建一个 token)
|
config.setIsShare(true); // 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token,为 false 时每次登录新建一个 token)
|
||||||
config.setTokenStyle("uuid"); // token 风格
|
config.setTokenStyle("uuid"); // token 风格
|
||||||
@ -92,7 +92,7 @@ public class SaTokenConfigure {
|
|||||||
public void configSaToken(SaTokenConfig config) {
|
public void configSaToken(SaTokenConfig config) {
|
||||||
config.setTokenName("satoken"); // token 名称(同时也是 cookie 名称)
|
config.setTokenName("satoken"); // token 名称(同时也是 cookie 名称)
|
||||||
config.setTimeout(30 * 24 * 60 * 60); // token 有效期(单位:秒),默认30天,-1代表永不过期
|
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.setIsConcurrent(true); // 是否允许同一账号多地同时登录(为 true 时允许一起登录,为 false 时新登录挤掉旧登录)
|
||||||
config.setIsShare(true); // 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token,为 false 时每次登录新建一个 token)
|
config.setIsShare(true); // 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token,为 false 时每次登录新建一个 token)
|
||||||
config.setTokenStyle("uuid"); // token 风格
|
config.setTokenStyle("uuid"); // token 风格
|
||||||
@ -116,7 +116,7 @@ public class SaTokenConfigure {
|
|||||||
| :-------- | :-------- | :-------- | :-------- |
|
| :-------- | :-------- | :-------- | :-------- |
|
||||||
| tokenName | String | satoken | Token 名称 (同时也是 Cookie 名称、数据持久化前缀) |
|
| tokenName | String | satoken | Token 名称 (同时也是 Cookie 名称、数据持久化前缀) |
|
||||||
| timeout | long | 2592000 | Token 有效期(单位:秒),默认30天,-1代表永不过期 [参考:token有效期详解](/fun/token-timeout) |
|
| 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 时新登录挤掉旧登录) |
|
| isConcurrent | Boolean | true | 是否允许同一账号并发登录 (为 true 时允许一起登录,为 false 时新登录挤掉旧登录) |
|
||||||
| isShare | Boolean | true | 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token,为 false 时每次登录新建一个 token) |
|
| isShare | Boolean | true | 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token,为 false 时每次登录新建一个 token) |
|
||||||
| maxLoginCount | int | 12 | 同一账号最大登录数量,-1代表不限 (只有在 `isConcurrent=true`,`isShare=false` 时此配置才有效),[详解](/use/config?id=配置项详解:maxlogincount) |
|
| maxLoginCount | int | 12 | 同一账号最大登录数量,-1代表不限 (只有在 `isConcurrent=true`,`isShare=false` 时此配置才有效),[详解](/use/config?id=配置项详解:maxlogincount) |
|
||||||
|
@ -89,7 +89,7 @@ public class StpLogicJwtForMixin extends StpLogic {
|
|||||||
info.tokenTimeout = getTokenTimeout();
|
info.tokenTimeout = getTokenTimeout();
|
||||||
info.sessionTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
|
info.sessionTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
|
||||||
info.tokenSessionTimeout = 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();
|
info.loginDevice = getLoginDevice();
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ public class StpLogicJwtForStateless extends StpLogic {
|
|||||||
info.tokenTimeout = getTokenTimeout();
|
info.tokenTimeout = getTokenTimeout();
|
||||||
info.sessionTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
|
info.sessionTimeout = SaTokenDao.NOT_VALUE_EXPIRE;
|
||||||
info.tokenSessionTimeout = 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();
|
info.loginDevice = getLoginDevice();
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ public class AtteStartListener implements JbootAppListener {
|
|||||||
SaTokenConfig saTokenConfig = new SaTokenConfig();
|
SaTokenConfig saTokenConfig = new SaTokenConfig();
|
||||||
saTokenConfig.setTokenStyle(SaTokenConsts.TOKEN_STYLE_SIMPLE_UUID);
|
saTokenConfig.setTokenStyle(SaTokenConsts.TOKEN_STYLE_SIMPLE_UUID);
|
||||||
saTokenConfig.setTimeout(60*60*4); //登录有效时间4小时
|
saTokenConfig.setTimeout(60*60*4); //登录有效时间4小时
|
||||||
saTokenConfig.setActivityTimeout(30*60); //半小时无操作过期处理
|
saTokenConfig.setActiveTimeout(30*60); //半小时无操作就冻结 token
|
||||||
saTokenConfig.setIsShare(false);
|
saTokenConfig.setIsShare(false);
|
||||||
saTokenConfig.setTokenName("token"); //更换satoken的名称
|
saTokenConfig.setTokenName("token"); //更换satoken的名称
|
||||||
saTokenConfig.setCookie(new SaCookieConfig().setHttpOnly(true)); //开启cookies的httponly属性
|
saTokenConfig.setCookie(new SaCookieConfig().setHttpOnly(true)); //开启cookies的httponly属性
|
||||||
|
@ -38,7 +38,7 @@ public class Config extends JFinalConfig {
|
|||||||
SaTokenConfig saTokenConfig = new SaTokenConfig();
|
SaTokenConfig saTokenConfig = new SaTokenConfig();
|
||||||
saTokenConfig.setTokenStyle(SaTokenConsts.TOKEN_STYLE_SIMPLE_UUID);
|
saTokenConfig.setTokenStyle(SaTokenConsts.TOKEN_STYLE_SIMPLE_UUID);
|
||||||
saTokenConfig.setTimeout(60*60*4); //登录有效时间4小时
|
saTokenConfig.setTimeout(60*60*4); //登录有效时间4小时
|
||||||
saTokenConfig.setActivityTimeout(30*60); //半小时无操作过期处理
|
saTokenConfig.setActiveTimeout(30*60); //半小时无操作就冻结 token
|
||||||
saTokenConfig.setIsShare(false);
|
saTokenConfig.setIsShare(false);
|
||||||
saTokenConfig.setTokenName("token"); //更改satoken的cookies名称
|
saTokenConfig.setTokenName("token"); //更改satoken的cookies名称
|
||||||
SaCookieConfig saCookieConfig = new SaCookieConfig();
|
SaCookieConfig saCookieConfig = new SaCookieConfig();
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
|
|
||||||
|
|
||||||
# sa-token配置
|
# sa-token 配置
|
||||||
sa-token:
|
sa-token:
|
||||||
# token名称 (同时也是cookie名称)
|
# token 名称 (同时也是 cookie 名称)
|
||||||
token-name: satoken
|
token-name: satoken
|
||||||
# token有效期,单位s 默认30天, -1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: -1
|
||||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
allow-concurrent-login: true
|
is-concurrent: true
|
||||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
is-share: true
|
is-share: true
|
||||||
# token风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
token-style: uuid
|
token-style: uuid
|
||||||
# 是否输出操作日志
|
# 是否输出操作日志
|
||||||
is-log: false
|
is-log: true
|
||||||
|
|
||||||
|
|
||||||
sa-token-dao: #名字可以随意取
|
sa-token-dao: #名字可以随意取
|
||||||
|
@ -2,19 +2,19 @@
|
|||||||
server:
|
server:
|
||||||
port: 8081
|
port: 8081
|
||||||
|
|
||||||
# sa-token配置
|
# sa-token 配置
|
||||||
sa-token:
|
sa-token:
|
||||||
# token名称 (同时也是cookie名称)
|
# token 名称 (同时也是 cookie 名称)
|
||||||
token-name: satoken
|
token-name: satoken
|
||||||
# token有效期,单位s 默认30天, -1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout: 2592000
|
timeout: 2592000
|
||||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activity-timeout: -1
|
active-timeout: -1
|
||||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
is-concurrent: true
|
is-concurrent: true
|
||||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
is-share: true
|
is-share: true
|
||||||
# token风格
|
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||||
token-style: uuid
|
token-style: uuid
|
||||||
# jwt秘钥
|
# jwt秘钥
|
||||||
jwt-secret-key: asdasdasifhueuiwyurfewbfjsdafjk
|
jwt-secret-key: asdasdasifhueuiwyurfewbfjsdafjk
|
||||||
|
@ -41,8 +41,8 @@ public class SaTokenConfigTest {
|
|||||||
config.setTimeout(100204);
|
config.setTimeout(100204);
|
||||||
Assertions.assertEquals(config.getTimeout(), 100204);
|
Assertions.assertEquals(config.getTimeout(), 100204);
|
||||||
|
|
||||||
config.setActivityTimeout(1804);
|
config.setActiveTimeout(1804);
|
||||||
Assertions.assertEquals(config.getActivityTimeout(), 1804);
|
Assertions.assertEquals(config.getActiveTimeout(), 1804);
|
||||||
|
|
||||||
config.setIsConcurrent(false);
|
config.setIsConcurrent(false);
|
||||||
Assertions.assertEquals(config.getIsConcurrent(), false);
|
Assertions.assertEquals(config.getIsConcurrent(), false);
|
||||||
@ -111,7 +111,7 @@ public class SaTokenConfigTest {
|
|||||||
SaTokenConfig config = SaTokenConfigFactory.createConfig("sa-token2.properties");
|
SaTokenConfig config = SaTokenConfigFactory.createConfig("sa-token2.properties");
|
||||||
Assertions.assertEquals(config.getTokenName(), "use-token");
|
Assertions.assertEquals(config.getTokenName(), "use-token");
|
||||||
Assertions.assertEquals(config.getTimeout(), 9000);
|
Assertions.assertEquals(config.getTimeout(), 9000);
|
||||||
Assertions.assertEquals(config.getActivityTimeout(), 240);
|
Assertions.assertEquals(config.getActiveTimeout(), 240);
|
||||||
Assertions.assertEquals(config.getIsConcurrent(), false);
|
Assertions.assertEquals(config.getIsConcurrent(), false);
|
||||||
Assertions.assertEquals(config.getIsShare(), false);
|
Assertions.assertEquals(config.getIsShare(), false);
|
||||||
Assertions.assertEquals(config.getIsLog(), true);
|
Assertions.assertEquals(config.getIsLog(), true);
|
||||||
|
@ -45,7 +45,7 @@ public class TokenInfoTest {
|
|||||||
info.setTokenTimeout(1800);
|
info.setTokenTimeout(1800);
|
||||||
info.setSessionTimeout(120);
|
info.setSessionTimeout(120);
|
||||||
info.setTokenSessionTimeout(1800);
|
info.setTokenSessionTimeout(1800);
|
||||||
info.setTokenActivityTimeout(120);
|
info.setTokenActiveTimeout(120);
|
||||||
info.setLoginDevice("PC");
|
info.setLoginDevice("PC");
|
||||||
info.setTag("xxx");
|
info.setTag("xxx");
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ public class TokenInfoTest {
|
|||||||
Assertions.assertEquals(info.getTokenTimeout(), 1800);
|
Assertions.assertEquals(info.getTokenTimeout(), 1800);
|
||||||
Assertions.assertEquals(info.getSessionTimeout(), 120);
|
Assertions.assertEquals(info.getSessionTimeout(), 120);
|
||||||
Assertions.assertEquals(info.getTokenSessionTimeout(), 1800);
|
Assertions.assertEquals(info.getTokenSessionTimeout(), 1800);
|
||||||
Assertions.assertEquals(info.getTokenActivityTimeout(), 120);
|
Assertions.assertEquals(info.getTokenActiveTimeout(), 120);
|
||||||
Assertions.assertEquals(info.getLoginDevice(), "PC");
|
Assertions.assertEquals(info.getLoginDevice(), "PC");
|
||||||
Assertions.assertEquals(info.getTag(), "xxx");
|
Assertions.assertEquals(info.getTag(), "xxx");
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ public class BasicsTest {
|
|||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static void beforeClass() {
|
public static void beforeClass() {
|
||||||
System.out.println("\n\n------------------------ 基础测试 star ...");
|
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");
|
Assertions.assertEquals(tokenSession.get("code"), "123456");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 测试,临时过期
|
// 测试,token 最低活跃频率
|
||||||
@Test
|
@Test
|
||||||
public void testActivityTimeout() {
|
public void testActiveTimeout() {
|
||||||
// 登录
|
// 登录
|
||||||
StpUtil.login(10001);
|
StpUtil.login(10001);
|
||||||
Assertions.assertNotNull(StpUtil.getTokenValue());
|
Assertions.assertNotNull(StpUtil.getTokenValue());
|
||||||
|
|
||||||
// 默认跟随全局 timeout
|
// 默认跟随全局 timeout
|
||||||
StpUtil.updateLastActivityToNow();
|
StpUtil.updateLastActiveToNow();
|
||||||
long activityTimeout = StpUtil.getTokenActivityTimeout();
|
long activeTimeout = StpUtil.getTokenActiveTimeout();
|
||||||
Assertions.assertTrue(activityTimeout <=180 || activityTimeout >=179);
|
Assertions.assertTrue(activeTimeout <=180 || activeTimeout >=179);
|
||||||
|
|
||||||
// 不会抛出异常
|
// 不会抛出异常
|
||||||
Assertions.assertDoesNotThrow(() -> StpUtil.checkActivityTimeout());
|
Assertions.assertDoesNotThrow(() -> StpUtil.checkActiveTimeout());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 测试,上下文 API
|
// 测试,上下文 API
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
# token名称 (同时也是cookie名称)
|
# token 名称 (同时也是 cookie 名称)
|
||||||
tokenName=use-token
|
tokenName=use-token
|
||||||
# token有效期,单位s 默认30天, -1代表永不过期
|
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||||
timeout=9000
|
timeout=9000
|
||||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||||
activityTimeout=240
|
activeTimeout=240
|
||||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) =-1
|
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||||
isConcurrent=false
|
isConcurrent=false
|
||||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||||
isShare=false
|
isShare=false
|
||||||
# token风格
|
# 是否输出操作日志
|
||||||
isLog=true
|
isLog=true
|
Loading…
Reference in New Issue
Block a user