1
0
mirror of synced 2026-05-22 22:53:16 +00:00

优化核心包代码注释 & 彩色日志打印

This commit is contained in:
click33
2023-05-08 13:47:59 +08:00
parent 31476cb5a0
commit 21edf27743
383 changed files with 2832 additions and 2033 deletions
@@ -28,14 +28,15 @@ import java.util.LinkedHashMap;
import java.util.Map;
/**
* 管理 Sa-Token 所有全局组件
* @author kong
* 管理 Sa-Token 所有全局组件,可通过此类快速获取、写入各种全局组件对象
*
* @author click33
* @since <= 1.34.0
*/
public class SaManager {
/**
* 配置文件 Bean
* 全局配置对象
*/
public volatile static SaTokenConfig config;
public static void setConfig(SaTokenConfig config) {
@@ -45,16 +46,26 @@ public class SaManager {
if(config !=null && config.getIsPrint()) {
SaFoxUtil.printSaToken();
}
// 如果此 config 对象没有配置 isColorLog 的值,则框架为它自动判断一下
if(config != null && config.getIsLog() != null && config.getIsLog() && config.getIsColorLog() == null) {
config.setIsColorLog(SaFoxUtil.isCanColorLog());
}
// $$ 全局事件
SaTokenEventCenter.doSetConfig(config);
// 调用一次StpUtil中的方法,保证其可以尽早的初始化 StpLogic
// 调用一次 StpUtil 中的方法,保证其可以尽早的初始化 StpLogic
StpUtil.getLoginType();
}
private static void setConfigMethod(SaTokenConfig config) {
SaManager.config = config;
}
/**
* 获取 Sa-Token 的全局配置信息
* @return
*/
public static SaTokenConfig getConfig() {
if (config == null) {
synchronized (SaManager.class) {
@@ -67,7 +78,7 @@ public class SaManager {
}
/**
* 持久化 Bean
* 持久化组件
*/
private volatile static SaTokenDao saTokenDao;
public static void setSaTokenDao(SaTokenDao saTokenDao) {
@@ -92,7 +103,7 @@ public class SaManager {
}
/**
* 权限认证 Bean
* 权限数据源组件
*/
private volatile static StpInterface stpInterface;
public static void setStpInterface(StpInterface stpInterface) {
@@ -111,7 +122,7 @@ public class SaManager {
}
/**
* 上下文Context Bean
* 一级上下文 SaTokenContextContext
*/
private volatile static SaTokenContext saTokenContext;
public static void setSaTokenContext(SaTokenContext saTokenContext) {
@@ -123,7 +134,7 @@ public class SaManager {
}
/**
* 二级Context
* 二级上下文 SaTokenSecondContext
*/
private volatile static SaTokenSecondContext saTokenSecondContext;
public static void setSaTokenSecondContext(SaTokenSecondContext saTokenSecondContext) {
@@ -135,7 +146,7 @@ public class SaManager {
}
/**
* 获取一个可用的SaTokenContext
* 获取一个可用的 SaTokenContext (按照一级上下文、二级上下文、默认上下文的顺序来判断)
* @return /
*/
public static SaTokenContext getSaTokenContextOrSecond() {
@@ -159,7 +170,7 @@ public class SaManager {
}
/**
* 临时令牌验证模块 Bean
* 临时 token 认证模块
*/
private volatile static SaTempInterface saTemp;
public static void setSaTemp(SaTempInterface saTemp) {
@@ -178,7 +189,7 @@ public class SaManager {
}
/**
* JSON 转换器 Bean
* JSON 转换器
*/
private volatile static SaJsonTemplate saJsonTemplate;
public static void setSaJsonTemplate(SaJsonTemplate saJsonTemplate) {
@@ -197,7 +208,7 @@ public class SaManager {
}
/**
* 参数签名 Bean
* API 参数签名
*/
private volatile static SaSignTemplate saSignTemplate;
public static void setSaSignTemplate(SaSignTemplate saSignTemplate) {
@@ -216,7 +227,7 @@ public class SaManager {
}
/**
* Same-Token Bean
* Same-Token 同源系统认证模块
*/
private volatile static SaSameTemplate saSameTemplate;
public static void setSaSameTemplate(SaSameTemplate saSameTemplate) {
@@ -247,7 +258,7 @@ public class SaManager {
}
/**
* StpLogic集合, 记录框架所有成功初始化的StpLogic
* StpLogic 集合, 记录框架所有成功初始化的 StpLogic
*/
public static Map<String, StpLogic> stpLogicMap = new LinkedHashMap<String, StpLogic>();
@@ -269,7 +280,7 @@ public class SaManager {
}
/**
* 根据 LoginType 获取对应的StpLogic,如果不存在,isCreate参数=是否自动创建并返回
* 根据 LoginType 获取对应的StpLogic,如果不存在,isCreate = 是否自动创建并返回
* @param loginType 对应的账号类型
* @param isCreate 在 StpLogic 不存在时,true=新建并返回,false=抛出异常
* @return 对应的StpLogic
@@ -1,17 +1,19 @@
package cn.dev33.satoken.annotation;
import cn.dev33.satoken.basic.SaBasicTemplate;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import cn.dev33.satoken.basic.SaBasicTemplate;
/**
* Http Basic 认证校验:只有通过 Basic 认证后才能进入该方法
* <p> 可标注在函数、类上(效果等同于标注在此类的所有方法上)
* @author kong
* Http Basic 认证校验:只有通过 Http Basic 认证后才能进入该方法,否则抛出异常。
*
* <p> 可标注在方法、类上(效果等同于标注在此类的所有方法上)
*
* @author click33
* @since <= 1.34.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
@@ -19,13 +21,13 @@ public @interface SaCheckBasic {
/**
* 领域
* @return see note
* @return /
*/
String realm() default SaBasicTemplate.DEFAULT_REALM;
/**
* 需要校验的账号密码,格式形如 sa:123456
* @return see note
* @return /
*/
String account() default "";
@@ -1,38 +1,40 @@
package cn.dev33.satoken.annotation;
import cn.dev33.satoken.util.SaTokenConsts;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import cn.dev33.satoken.util.SaTokenConsts;
/**
* 服务禁用校验:在没有被禁用指定服务的情况下才可以进入方法
* 服务禁用校验:判断当前账号是否被禁用指定服务,如果被禁用,会抛出异常,没有被禁用才能进入方法
*
* <p> 可标注在函数、类上(效果等同于标注在此类的所有方法上)
* <p> 可标注在方法、类上(效果等同于标注在此类的所有方法上)
*
* @author videomonster
* @since <= 1.34.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
public @interface SaCheckDisable {
/**
* 多账号体系下所属的账号体系标识
* @return see note
* 多账号体系下所属的账号体系标识,非多账号体系无需关注此值
*
* @return /
*/
String type() default "";
/**
* 服务标识 (要校验是否禁用的服务名称)
* 服务标识 具体你要校验是否禁用的服务名称)
*
* @return see note
* @return /
*/
String[] value() default { SaTokenConsts.DEFAULT_DISABLE_SERVICE };
/**
* 封禁等级(只有 封禁等级 ≥ 此值 才会抛出异常
* 封禁等级(如果当前账号的被封禁等级 ≥ 此值,请求就无法进入方法
*
* @return /
*/
@@ -6,18 +6,21 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 登录认证校验:只有登录之后才能进入该方法
* <p> 可标注在函数、类上(效果等同于标注在此类的所有方法上)
* @author kong
* 登录认证校验:只有登录之后才能进入该方法
*
* <p> 可标注在方法、类上(效果等同于标注在此类的所有方法上)
*
* @author kong
* @since <= 1.34.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
public @interface SaCheckLogin {
/**
* 多账号体系下所属的账号体系标识
* @return see note
* 多账号体系下所属的账号体系标识,非多账号体系无需关注此值
*
* @return /
*/
String type() default "";
@@ -6,44 +6,49 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 权限认证校验:必须具有指定权限才能进入该方法
* <p> 可标注在函数、类上(效果等同于标注在此类的所有方法上)
* @author kong
* 权限认证校验:必须具有指定权限才能进入该方法
*
* <p> 可标注在方法、类上(效果等同于标注在此类的所有方法上)
*
* @author click33
* @since <= 1.34.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface SaCheckPermission {
/**
* 需要校验的权限码
* @return 需要校验的权限码
* 多账号体系下所属的账号体系标识,非多账号体系无需关注此值
*
* @return /
*/
String type() default "";
/**
* 需要校验的权限码 [ 数组 ]
*
* @return /
*/
String [] value() default {};
/**
* 验证模式:AND | OR,默认AND
* @return 验证模式
*
* @return /
*/
SaMode mode() default SaMode.AND;
/**
* 多账号体系下所属的账号体系标识
* @return see note
*/
String type() default "";
/**
* 在权限认证不通过时的次要选择,两者只要其一认证成功即可通过校验
* 在权限校验不通过时的次要选择,两者只要其一校验成功即可通过校验
*
* <p>
* 例1@SaCheckPermission(value="user-add", orRole="admin")
* 代表本次请求只要具有 user-add权限 或 admin角色 其一即可通过校验
* 代表本次请求只要具有 user-add权限 或 admin角色 其一即可通过校验
* </p>
*
* <p>
* 例2 orRole = {"admin", "manager", "staff"},具有三个角色其一即可 <br>
* 例3 orRole = {"admin, manager, staff"},必须三个角色同时具备
* 例2 orRole = {"admin", "manager", "staff"},具有三个角色其一即可 <br>
* 例3 orRole = {"admin, manager, staff"},必须三个角色同时具备
* </p>
*
* @return /
@@ -6,32 +6,36 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 角色认证校验:必须具有指定角色标识才能进入该方法
* <p> 可标注在函数、类上(效果等同于标注在此类的所有方法上)
* @author kong
* 角色认证校验:必须具有指定角色标识才能进入该方法
*
* <p> 可标注在方法、类上(效果等同于标注在此类的所有方法上)
*
* @author click33
* @since <= 1.34.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface SaCheckRole {
/**
* 需要校验的角色标识
* @return 需要校验的角色标识
* 多账号体系下所属的账号体系标识,非多账号体系无需关注此值
*
* @return /
*/
String type() default "";
/**
* 需要校验的角色标识 [ 数组 ]
*
* @return /
*/
String [] value() default {};
/**
* 验证模式:AND | OR,默认AND
* @return 验证模式
*
* @return /
*/
SaMode mode() default SaMode.AND;
/**
* 账号类型
* <p> 建议使用常量,避免因错误拼写带来的bug
* @return see note
*/
String type() default "";
}
@@ -8,24 +8,27 @@ import java.lang.annotation.Target;
import cn.dev33.satoken.util.SaTokenConsts;
/**
* 二级认证校验:必须二级认证之后才能进入该方法
* 二级认证校验:客户端必须完成二级认证之后才能进入该方法,否则将被抛出异常。
*
* <p> 可标注在函数、类上(效果等同于标注在此类的所有方法上)
* @author kong
* <p> 可标注在方法、类上(效果等同于标注在此类的所有方法上)
*
* @author click33
* @since <= 1.34.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
public @interface SaCheckSafe {
/**
* 多账号体系下所属的账号体系标识
* @return /
*/
/**
* 多账号体系下所属的账号体系标识,非多账号体系无需关注此值
*
* @return /
*/
String type() default "";
/**
* 要校验的服务
* 要校验的服务
*
* @return /
*/
String value() default SaTokenConsts.DEFAULT_SAFE_AUTH_SERVICE;
@@ -6,12 +6,12 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 忽略认证:表示被修饰的方法或类无需进行注解认证和路由拦截认证
* 忽略认证:表示被修饰的方法或类无需进行注解认证和路由拦截认证
*
* <h2> 请注意:此注解的忽略效果只针对 SaInterceptor拦截器 和 AOP注解鉴权 生效,对自定义拦截器与过滤器不生效 </h2>
* <h3> 请注意:此注解的忽略效果只针对 SaInterceptor拦截器 和 AOP注解鉴权 生效,对自定义拦截器与过滤器不生效 </h3>
*
* @author kong
* @since: 2022-8-21
* @author click33
* @since <= 1.34.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
@@ -1,9 +1,10 @@
package cn.dev33.satoken.annotation;
/**
* 注解鉴权的验证模式
* @author kong
* 注解鉴权的验证模式
*
* @author click33
* @since <= 1.34.0
*/
public enum SaMode {
@@ -7,10 +7,11 @@ import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.dao.SaTokenDao;
/**
* Application Model,全局作用域的读取值对象
* <p> 在应用全局范围内: 存值、取值
* Application Model,全局作用域的读取值对象
*
* <p> 在应用全局范围内: 存值、取值。数据在应用重启后失效,如果集成了 Redis,则在 Redis 重启后失效。
*
* @author kong
* @author click33
* @since: 2022-8-17
*/
public class SaApplication implements SaSetValueInterface {
@@ -57,15 +58,15 @@ public class SaApplication implements SaSetValueInterface {
}
/**
* 返回存入的所有 key
* 返回当前存入的所有 key
* @return /
*/
public List<String> keys() {
// 查出来
// 从缓存中查询出所有此前缀的 key
String prefix = splicingDataKey("");
List<String> list = SaManager.getSaTokenDao().searchData(prefix, "", 0, -1, true);
// 裁减掉固定前缀
// 裁减掉固定前缀,保留 key 名称,塞入新集合
int prefixLength = prefix.length();
List<String> list2 = new ArrayList<>();
if(list != null) {
@@ -79,7 +80,7 @@ public class SaApplication implements SaSetValueInterface {
}
/**
* 清空存入的所有 key
* 清空当前存入的所有 key
*/
public void clear() {
List<String> keys = keys();
@@ -89,7 +90,8 @@ public class SaApplication implements SaSetValueInterface {
}
/**
* 拼接key变量存储时使用的key
* 拼接key当存入一个变量时,应该使用的 key
*
* @param key 原始 key
* @return 拼接后的 key 值
*/
@@ -3,9 +3,10 @@ package cn.dev33.satoken.application;
import cn.dev33.satoken.util.SaFoxUtil;
/**
* 对取值的一组方法封装
* 对取值的一组方法封装
* <p> 封装 SaStorage、SaSession、SaApplication 等存取值的一些固定方法,减少重复编码 </p>
*
* @author kong
* @author click33
* @since: 2022-8-16
*/
public interface SaGetValueInterface {
@@ -17,20 +18,20 @@ public interface SaGetValueInterface {
* @param key key
* @return 值
*/
public abstract Object get(String key);
Object get(String key);
// --------- 接口提供封装的方法
/**
*
* 取值 (指定默认值)
* 取值 (指定默认值)
*
* @param <T> 默认值的类型
* @param key key
* @param defaultValue 取不到值时返回的默认值
* @return 值
*/
public default <T> T get(String key, T defaultValue) {
default <T> T get(String key, T defaultValue) {
return getValueByDefaultValue(get(key), defaultValue);
}
@@ -39,7 +40,7 @@ public interface SaGetValueInterface {
* @param key key
* @return 值
*/
public default String getString(String key) {
default String getString(String key) {
Object value = get(key);
if(value == null) {
return null;
@@ -52,7 +53,7 @@ public interface SaGetValueInterface {
* @param key key
* @return 值
*/
public default int getInt(String key) {
default int getInt(String key) {
return getValueByDefaultValue(get(key), 0);
}
@@ -61,7 +62,7 @@ public interface SaGetValueInterface {
* @param key key
* @return 值
*/
public default long getLong(String key) {
default long getLong(String key) {
return getValueByDefaultValue(get(key), 0L);
}
@@ -70,7 +71,7 @@ public interface SaGetValueInterface {
* @param key key
* @return 值
*/
public default double getDouble(String key) {
default double getDouble(String key) {
return getValueByDefaultValue(get(key), 0.0);
}
@@ -79,7 +80,7 @@ public interface SaGetValueInterface {
* @param key key
* @return 值
*/
public default float getFloat(String key) {
default float getFloat(String key) {
return getValueByDefaultValue(get(key), 0.0f);
}
@@ -90,12 +91,12 @@ public interface SaGetValueInterface {
* @param cs 指定转换类型
* @return 值
*/
public default <T> T getModel(String key, Class<T> cs) {
default <T> T getModel(String key, Class<T> cs) {
return SaFoxUtil.getValueByType(get(key), cs);
}
/**
* 取值 (指定转换类型, 并指定值为Null时返回的默认值)
* 取值 (指定转换类型, 并指定值为 null 时返回的默认值)
* @param <T> 泛型
* @param key key
* @param cs 指定转换类型
@@ -103,7 +104,7 @@ public interface SaGetValueInterface {
* @return 值
*/
@SuppressWarnings("unchecked")
public default <T> T getModel(String key, Class<T> cs, Object defaultValue) {
default <T> T getModel(String key, Class<T> cs, Object defaultValue) {
Object value = get(key);
if(valueIsNull(value)) {
return (T)defaultValue;
@@ -112,11 +113,11 @@ public interface SaGetValueInterface {
}
/**
* 是否含有某个key
* @param key has
* 是否含有某个 key
* @param key 指定 key
* @return 是否含有
*/
public default boolean has(String key) {
default boolean has(String key) {
return !valueIsNull(get(key));
}
@@ -128,7 +129,7 @@ public interface SaGetValueInterface {
* @param value 指定值
* @return 此value是否为null
*/
public default boolean valueIsNull(Object value) {
default boolean valueIsNull(Object value) {
return value == null || value.equals("");
}
@@ -140,14 +141,14 @@ public interface SaGetValueInterface {
* @return 转换后的值
*/
@SuppressWarnings("unchecked")
public default <T> T getValueByDefaultValue(Object value, T defaultValue) {
default <T> T getValueByDefaultValue(Object value, T defaultValue) {
// 如果 obj 为 null,则直接返回默认值
if(valueIsNull(value)) {
return (T)defaultValue;
}
// 开始转换
// 开始转换类型
Class<T> cs = (Class<T>) defaultValue.getClass();
return SaFoxUtil.getValueByType(value, cs);
}
@@ -3,9 +3,10 @@ package cn.dev33.satoken.application;
import cn.dev33.satoken.fun.SaRetFunction;
/**
* 对写值的一组方法封装
* 对写值的一组方法封装
* <p> 封装 SaStorage、SaSession、SaApplication 等存取值的一些固定方法,减少重复编码 </p>
*
* @author kong
* @author click33
* @since: 2022-8-17
*/
public interface SaSetValueInterface extends SaGetValueInterface {
@@ -8,19 +8,20 @@ import cn.dev33.satoken.secure.SaBase64Util;
import cn.dev33.satoken.util.SaFoxUtil;
/**
* Sa-Token Http Basic 认证模块
* @author kong
* Sa-Token Http Basic 认证模块
*
* @author click33
* @since <= 1.34.0
*/
public class SaBasicTemplate {
/**
* 默认的 Realm 名称
* 默认的 Realm 领域名称
*/
public static final String DEFAULT_REALM = "Sa-Token";
/**
* 设置响应头,并抛出异常
* 在校验失败时,设置响应头,并抛出异常
* @param realm 领域
*/
public void throwNotBasicAuthException(String realm) {
@@ -34,7 +35,7 @@ public class SaBasicTemplate {
*/
public String getAuthorizationValue() {
// 获取请求头 Authorization 参数
// 获取前端提交的请求头 Authorization 参数
String authorization = SaHolder.getRequest().getHeader("Authorization");
// 如果不是以 Basic 作为前缀,则视为无效
@@ -1,9 +1,10 @@
package cn.dev33.satoken.basic;
/**
* Sa-Token Http Basic 认证 Util
* @author kong
* Sa-Token Http Basic 认证模块,Util 工具类
*
* @author click33
* @since <= 1.34.0
*/
public class SaBasicUtil {
@@ -11,7 +12,7 @@ public class SaBasicUtil {
}
/**
* 底层 SaBasicTemplate 对象
* 底层使用的 SaBasicTemplate 对象
*/
public static SaBasicTemplate saBasicTemplate = new SaBasicTemplate();
@@ -1,24 +1,31 @@
package cn.dev33.satoken.config;
/**
* Sa-Token Cookie写入 相关配置
* @author kong
* Sa-Token Cookie写入 相关配置
*
* @author click33
* @since <= 1.34.0
*/
public class SaCookieConfig {
/*
Cookie 功能为浏览器通用标准,建议大家自行搜索文章了解各个属性的功能含义,此处源码仅做简单解释。
*/
/**
* 域(写入Cookie时显式指定的作用域, 常用于单点登录二级域名共享Cookie的场景)
* 作用
* <p> 写入 Cookie 时显式指定的作用域, 常用于单点登录二级域名共享 Cookie 的场景。 </p>
* <p> 一般情况下你不需要设置此值,因为浏览器默认会把 Cookie 写到当前域名下。 </p>
*/
private String domain;
/**
* 路径
* 路径 (一般只有当你在一个域名下部署多个项目时才会用到此值。)
*/
private String path;
/**
* 是否只在 https 协议下有效
* 是否只在 https 协议下有效
*/
private Boolean secure = false;
@@ -33,14 +40,20 @@ public class SaCookieConfig {
private String sameSite;
/**
* @return 域 (写入Cookie时显式指定的作用域, 常用于单点登录二级域名共享Cookie的场景)
* 获取:Cookie 作用域
* <p> 写入 Cookie 时显式指定的作用域, 常用于单点登录二级域名共享 Cookie 的场景。 </p>
* <p> 一般情况下你不需要设置此值,因为浏览器默认会把 Cookie 写到当前域名下。 </p>
* @return /
*/
public String getDomain() {
return domain;
}
/**
* @param domain 域 写入Cookie时显式指定的作用域, 常用于单点登录二级域名共享Cookie的场景)
* 写入Cookie 作用域
* <p> 写入 Cookie 时显式指定的作用域, 常用于单点登录二级域名共享 Cookie 的场景。 </p>
* <p> 一般情况下你不需要设置此值,因为浏览器默认会把 Cookie 写到当前域名下。 </p>
* @param domain /
* @return 对象自身
*/
public SaCookieConfig setDomain(String domain) {
@@ -49,14 +62,14 @@ public class SaCookieConfig {
}
/**
* @return 路径
* @return 路径 (一般只有当你在一个域名下部署多个项目时才会用到此值。)
*/
public String getPath() {
return path;
}
/**
* @param path 路径
* @param path 路径 (一般只有当你在一个域名下部署多个项目时才会用到此值。)
* @return 对象自身
*/
public SaCookieConfig setPath(String path) {
@@ -15,6 +15,9 @@ public class SaSignConfig {
/**
* 接口调用时的时间戳允许的差距(单位:ms),-1代表不校验差距,默认15分钟
*
* <p> 比如此处你配置了60秒,当一个请求从 client 发起后,如果 server 端60秒内没有处理,60秒后再想处理就无法校验通过了。</p>
* <p> timestamp + nonce 有效防止重放攻击。 </p>
*/
private long timestampDisparity = 1000 * 60 * 15;
@@ -47,6 +50,9 @@ public class SaSignConfig {
/**
* 获取 接口调用时的时间戳允许的差距(单位:ms),-1代表不校验差距,默认15分钟
*
* <p> 比如此处你配置了60秒,当一个请求从 client 发起后,如果 server 端60秒内没有处理,60秒后再想处理就无法校验通过了。</p>
* <p> timestamp + nonce 有效防止重放攻击。 </p>
*
* @return /
*/
public long getTimestampDisparity() {
@@ -56,6 +62,9 @@ public class SaSignConfig {
/**
* 设置 接口调用时的时间戳允许的差距(单位:ms),-1代表不校验差距,默认15分钟
*
* <p> 比如此处你配置了60秒,当一个请求从 client 发起后,如果 server 端60秒内没有处理,60秒后再想处理就无法校验通过了。</p>
* <p> timestamp + nonce 有效防止重放攻击。 </p>
*
* @param timestampDisparity /
* @return 对象自身
*/
@@ -5,95 +5,132 @@ import cn.dev33.satoken.util.SaFoxUtil;
import java.io.Serializable;
/**
* Sa-Token 配置类 Model
* <p>
* 你可以通过yml、properties、java代码等形式配置本类参数,具体请查阅官方文档: https://sa-token.cc/
*
* @author kong
* Sa-Token 配置类 Model
*
* <p> 你可以通过yml、properties、java代码等形式配置本类参数,具体请查阅官方文档: https://sa-token.cc/ </p>
*
* @author click33
* @since <= 1.34.0
*/
public class SaTokenConfig implements Serializable {
private static final long serialVersionUID = -6541180061782004705L;
/** token名称 (同时也是cookie名称) */
/** token 名称 同时也是 cookie 名称、提交 token 时参数的名称、存储 token 时的 key 前缀) */
private String tokenName = "satoken";
/** token的长久有效期(单位:秒) 默认30天, -1代表永久 */
/** token 的长久有效期单位:秒 默认30天, -1代表永久 */
private long timeout = 60 * 60 * 24 * 30;
/**
* token临时有效期 [指定时间内无操作就视为token过期] (单位: 秒), 默认-1 代表不限制
* (例如可以设置为1800代表30分钟内无操作就过期)
* token 临时有效期 [ 指定时间内无操作就视为 token 过期 ] 单位: 秒, 默认-1 代表不限制
* 例如可以设置为 1800 代表 30 分钟内无操作就过期
*/
private long activityTimeout = -1;
/** 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) */
/**
* 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
*/
private Boolean isConcurrent = true;
/** 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) */
/**
* 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
*/
private Boolean isShare = true;
/**
* 同一账号最大登录数量,-1代表不限 (只有在 isConcurrent=true, isShare=false 时此配置才有
* 同一账号最大登录数量,-1代表不限 (只有在 isConcurrent=true, isShare=false 时此配置才有意义
*/
private int maxLoginCount = 12;
/** 在每次创建 token 时的最高循环次数,用于保证 token 唯一性(-1=不循环尝试,直接使用) */
/**
* 在每次创建 token 时的最高循环次数,用于保证 token 唯一性(-1=不循环尝试,直接使用)
*/
private int maxTryTimes = 12;
/** 是否尝试从请求体里读取token */
/**
* 是否尝试从请求体里读取 token
*/
private Boolean isReadBody = true;
/** 是否尝试从header里读取token */
/**
* 是否尝试从 header 里读取 token
*/
private Boolean isReadHeader = true;
/** 是否尝试从cookie里读取token */
/**
* 是否尝试从 cookie 里读取 token
*/
private Boolean isReadCookie = true;
/** 是否在登录后将 Token 写入到响应头 */
/**
* 是否在登录后将 token 写入到响应头
*/
private Boolean isWriteHeader = false;
/** token风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik) */
private String tokenStyle = "uuid";
/** 默认dao层实现类中,每次清理过期数据间隔的时间 (单位: 秒) ,默认值30秒,设置为-1代表不启动定时清理 */
private int dataRefreshPeriod = 30;
/** 获取[token专属session]时是否必须登录 (如果配置为true,会在每次获取[token-session]时校验是否登录) */
private Boolean tokenSessionCheckLogin = true;
/** 是否打开自动续签 (如果此值为true, 框架会在每次直接或间接调用getLoginId()时进行一次过期检查与续签操作) */
private Boolean autoRenew = true;
/** token前缀, 格式样例(satoken: Bearer xxxx-xxxx-xxxx-xxxx) */
private String tokenPrefix;
/** 是否在初始化配置时打印版本字符画 */
private Boolean isPrint = true;
/** 是否打印操作日志 */
private Boolean isLog = false;
/** 日志等级(trace、debug、info、warn、error、fatal */
private String logLevel = "trace";
/** 日志等级 int 值(1=trace、2=debug、3=info、4=warn、5=error、6=fatal */
private int logLevelInt = 1;
/**
* jwt秘钥 (只有集成 jwt 模块时此参数才会生效)
* token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik
*/
private String tokenStyle = "uuid";
/**
* 默认 SaTokenDao 实现类中,每次清理过期数据间隔的时间(单位: 秒),默认值30秒,设置为-1代表不启动定时清理
*/
private int dataRefreshPeriod = 30;
/**
* 获取 Token-Session 时是否必须登录(如果配置为true,会在每次获取 getTokenSession() 时校验当前是否登录)
*/
private Boolean tokenSessionCheckLogin = true;
/**
* 是否打开自动续签 activityTimeout (如果此值为 true, 框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作)
*/
private Boolean autoRenew = true;
/**
* token 前缀, 前端提交 token 时应该填写的固定前缀,格式样例(satoken: Bearer xxxx-xxxx-xxxx-xxxx)
*/
private String tokenPrefix;
/**
* 是否在初始化配置时在控制台打印版本字符画
*/
private Boolean isPrint = true;
/**
* 是否打印操作日志
*/
private Boolean isLog = false;
/**
* 日志等级(trace、debug、info、warn、error、fatal),此值与 logLevelInt 联动
*/
private String logLevel = "trace";
/**
* 日志等级 int 值(1=trace、2=debug、3=info、4=warn、5=error、6=fatal),此值与 logLevel 联动
*/
private int logLevelInt = 1;
/**
* 是否打印彩色日志
*/
private Boolean isColorLog = null;
/**
* jwt秘钥(只有集成 jwt 相关模块时此参数才会生效)
*/
private String jwtSecretKey;
/**
* Http Basic 认证的账号和密码
* Http Basic 认证的默认账号和密码
*/
private String basic = "";
/** 配置当前项目的网络访问地址 */
/**
* 配置当前项目的网络访问地址
*/
private String currDomain;
/**
@@ -101,10 +138,11 @@ public class SaTokenConfig implements Serializable {
*/
private long sameTokenTimeout = 60 * 60 * 24;
/** 是否校验Same-Token(部分rpc插件有效) */
/**
* 是否校验 Same-Token(部分rpc插件有效)
*/
private Boolean checkSameToken = false;
/**
* Cookie配置对象
*/
@@ -117,14 +155,14 @@ public class SaTokenConfig implements Serializable {
/**
* @return token名称 (同时也是cookie名称)
* @return token 名称 同时也是 cookie 名称、提交 token 时参数的名称、存储 token 时的 key 前缀)
*/
public String getTokenName() {
return tokenName;
}
/**
* @param tokenName token名称 (同时也是cookie名称)
* @param tokenName token 名称 同时也是 cookie 名称、提交 token 时参数的名称、存储 token 时的 key 前缀)
* @return 对象自身
*/
public SaTokenConfig setTokenName(String tokenName) {
@@ -133,14 +171,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return token的长久有效期(单位:秒) 默认30天, -1代表永久
* @return token 的长久有效期单位:秒 默认30天, -1代表永久
*/
public long getTimeout() {
return timeout;
}
/**
* @param timeout token的长久有效期(单位:秒) 默认30天, -1代表永久
* @param timeout token 的长久有效期单位:秒 默认30天, -1代表永久
* @return 对象自身
*/
public SaTokenConfig setTimeout(long timeout) {
@@ -149,16 +187,16 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return token临时有效期 [指定时间内无操作就视为token过期] (单位: 秒), 默认-1 代表不限制
* (例如可以设置为1800代表30分钟内无操作就过期)
* @return token 临时有效期 [ 指定时间内无操作就视为 token 过期 ] 单位: 秒, 默认-1 代表不限制
* 例如可以设置为 1800 代表 30 分钟内无操作就过期
*/
public long getActivityTimeout() {
return activityTimeout;
}
/**
* @param activityTimeout token临时有效期 [指定时间内无操作就视为token过期] (单位: 秒), 默认-1 代表不限制
* (例如可以设置为1800代表30分钟内无操作就过期)
* @param activityTimeout token 临时有效期 [ 指定时间内无操作就视为 token 过期 ] 单位: 秒, 默认-1 代表不限制
* 例如可以设置为 1800 代表 30 分钟内无操作就过期
* @return 对象自身
*/
public SaTokenConfig setActivityTimeout(long activityTimeout) {
@@ -167,14 +205,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
* @return 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录
*/
public Boolean getIsConcurrent() {
return isConcurrent;
}
/**
* @param isConcurrent 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
* @param isConcurrent 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录
* @return 对象自身
*/
public SaTokenConfig setIsConcurrent(Boolean isConcurrent) {
@@ -183,14 +221,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
* @return 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个token, 为 false 时每次登录新建一个 token
*/
public Boolean getIsShare() {
return isShare;
}
/**
* @param isShare 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
* @param isShare 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个token, 为 false 时每次登录新建一个 token
* @return 对象自身
*/
public SaTokenConfig setIsShare(Boolean isShare) {
@@ -199,14 +237,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return 同一账号最大登录数量,-1代表不限 (只有在 isConcurrent=true, isShare=false 时此配置才有
* @return 同一账号最大登录数量,-1代表不限 (只有在 isConcurrent=true, isShare=false 时此配置才有意义
*/
public int getMaxLoginCount() {
return maxLoginCount;
}
/**
* @param maxLoginCount 同一账号最大登录数量,-1代表不限 (只有在 isConcurrent=true, isShare=false 时此配置才有
* @param maxLoginCount 同一账号最大登录数量,-1代表不限 (只有在 isConcurrent=true, isShare=false 时此配置才有意义
* @return 对象自身
*/
public SaTokenConfig setMaxLoginCount(int maxLoginCount) {
@@ -231,14 +269,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return 是否尝试从请求体里读取token
* @return 是否尝试从请求体里读取 token
*/
public Boolean getIsReadBody() {
return isReadBody;
}
/**
* @param isReadBody 是否尝试从请求体里读取token
* @param isReadBody 是否尝试从请求体里读取 token
* @return 对象自身
*/
public SaTokenConfig setIsReadBody(Boolean isReadBody) {
@@ -247,14 +285,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return 是否尝试从header里读取token
* @return 是否尝试从 header 里读取 token
*/
public Boolean getIsReadHeader() {
return isReadHeader;
}
/**
* @param isReadHeader 是否尝试从header里读取token
* @param isReadHeader 是否尝试从 header 里读取 token
* @return 对象自身
*/
public SaTokenConfig setIsReadHeader(Boolean isReadHeader) {
@@ -263,14 +301,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return 是否尝试从cookie里读取token
* @return 是否尝试从 cookie 里读取 token
*/
public Boolean getIsReadCookie() {
return isReadCookie;
}
/**
* @param isReadCookie 是否尝试从cookie里读取token
* @param isReadCookie 是否尝试从 cookie 里读取 token
* @return 对象自身
*/
public SaTokenConfig setIsReadCookie(Boolean isReadCookie) {
@@ -279,14 +317,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return 是否在登录后将 Token 写入到响应头
* @return 是否在登录后将 token 写入到响应头
*/
public Boolean getIsWriteHeader() {
return isWriteHeader;
}
/**
* @param isWriteHeader 是否在登录后将 Token 写入到响应头
* @param isWriteHeader 是否在登录后将 token 写入到响应头
* @return 对象自身
*/
public SaTokenConfig setIsWriteHeader(Boolean isWriteHeader) {
@@ -295,14 +333,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return token风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
* @return token 风格默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik
*/
public String getTokenStyle() {
return tokenStyle;
}
/**
* @param tokenStyle token风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
* @param tokenStyle token 风格默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik
* @return 对象自身
*/
public SaTokenConfig setTokenStyle(String tokenStyle) {
@@ -311,15 +349,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return 默认dao层实现类中,每次清理过期数据间隔的时间 (单位: 秒) ,默认值30秒,设置为-1代表不启动定时清理
* @return 默认 SaTokenDao 实现类中,每次清理过期数据间隔的时间单位: 秒,默认值30秒,设置为-1代表不启动定时清理
*/
public int getDataRefreshPeriod() {
return dataRefreshPeriod;
}
/**
* @param dataRefreshPeriod 默认dao层实现类中,每次清理过期数据间隔的时间 (单位: 秒)
* ,默认值30秒,设置为-1代表不启动定时清理
* @param dataRefreshPeriod 默认 SaTokenDao 实现类中,每次清理过期数据间隔的时间单位: 秒),默认值30秒,设置为-1代表不启动定时清理
* @return 对象自身
*/
public SaTokenConfig setDataRefreshPeriod(int dataRefreshPeriod) {
@@ -328,15 +365,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return 获取[token专属session]时是否必须登录 (如果配置为true,会在每次获取[token-session]时校验是否登录)
* @return 获取 Token-Session 时是否必须登录如果配置为true,会在每次获取 getTokenSession() 时校验当前是否登录
*/
public Boolean getTokenSessionCheckLogin() {
return tokenSessionCheckLogin;
}
/**
* @param tokenSessionCheckLogin 获取[token专属session]时是否必须登录
* (如果配置为true,会在每次获取[token-session]时校验是否登录)
* @param tokenSessionCheckLogin 获取 Token-Session 时是否必须登录(如果配置为true,会在每次获取 getTokenSession() 时校验当前是否登录)
* @return 对象自身
*/
public SaTokenConfig setTokenSessionCheckLogin(Boolean tokenSessionCheckLogin) {
@@ -345,14 +381,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return 是否打开自动续签 (如果此值为true, 框架会在每次直接或间接调用getLoginId()时进行一次过期检查与续签操作)
* @return 是否打开自动续签 activityTimeout 如果此值为 true, 框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作
*/
public Boolean getAutoRenew() {
return autoRenew;
}
/**
* @param autoRenew 是否打开自动续签 (如果此值为true, 框架会在每次直接或间接调用getLoginId()时进行一次过期检查与续签操作)
* @param autoRenew 是否打开自动续签 activityTimeout 如果此值为 true, 框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作
* @return 对象自身
*/
public SaTokenConfig setAutoRenew(Boolean autoRenew) {
@@ -361,14 +397,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return token前缀, 格式样例(satoken: Bearer xxxx-xxxx-xxxx-xxxx)
* @return token 前缀, 前端提交 token 时应该填写的固定前缀,格式样例(satoken: Bearer xxxx-xxxx-xxxx-xxxx)
*/
public String getTokenPrefix() {
return tokenPrefix;
}
/**
* @param tokenPrefix token前缀, 格式样例(satoken: Bearer xxxx-xxxx-xxxx-xxxx)
* @param tokenPrefix token 前缀, 前端提交 token 时应该填写的固定前缀,格式样例(satoken: Bearer xxxx-xxxx-xxxx-xxxx)
* @return 对象自身
*/
public SaTokenConfig setTokenPrefix(String tokenPrefix) {
@@ -377,14 +413,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return 是否在初始化配置时打印版本字符画
* @return 是否在初始化配置时在控制台打印版本字符画
*/
public Boolean getIsPrint() {
return isPrint;
}
/**
* @param isPrint 是否在初始化配置时打印版本字符画
* @param isPrint 是否在初始化配置时在控制台打印版本字符画
* @return 对象自身
*/
public SaTokenConfig setIsPrint(Boolean isPrint) {
@@ -409,14 +445,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return 日志等级(trace、debug、info、warn、error、fatal
* @return 日志等级(trace、debug、info、warn、error、fatal,此值与 logLevelInt 联动
*/
public String getLogLevel() {
return logLevel;
}
/**
* @param logLevel 日志等级(trace、debug、info、warn、error、fatal
* @param logLevel 日志等级(trace、debug、info、warn、error、fatal,此值与 logLevelInt 联动
* @return 对象自身
*/
public SaTokenConfig setLogLevel(String logLevel) {
@@ -426,14 +462,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return 日志等级 int 值(1=trace、2=debug、3=info、4=warn、5=error、6=fatal
* @return 日志等级 int 值(1=trace、2=debug、3=info、4=warn、5=error、6=fatal,此值与 logLevel 联动
*/
public int getLogLevelInt() {
return logLevelInt;
}
/**
* @param logLevelInt 日志等级 int 值(1=trace、2=debug、3=info、4=warn、5=error、6=fatal
* @param logLevelInt 日志等级 int 值(1=trace、2=debug、3=info、4=warn、5=error、6=fatal,此值与 logLevel 联动
* @return 对象自身
*/
public SaTokenConfig setLogLevelInt(int logLevelInt) {
@@ -441,16 +477,36 @@ public class SaTokenConfig implements Serializable {
this.logLevel = SaFoxUtil.translateLogLevelToString(logLevelInt);
return this;
}
/**
* @return jwt秘钥 (只有集成 jwt 模块时此参数才会生效)
* 获取:是否打印彩色日志
*
* @return isColorLog 是否打印彩色日志
*/
public Boolean getIsColorLog() {
return this.isColorLog;
}
/**
* 设置:是否打印彩色日志
*
* @param isColorLog 是否打印彩色日志
* @return 对象自身
*/
public SaTokenConfig setIsColorLog(Boolean isColorLog) {
this.isColorLog = isColorLog;
return this;
}
/**
* @return jwt秘钥(只有集成 jwt 相关模块时此参数才会生效)
*/
public String getJwtSecretKey() {
return jwtSecretKey;
}
/**
* @param jwtSecretKey jwt秘钥 (只有集成 jwt 模块时此参数才会生效)
* @param jwtSecretKey jwt秘钥只有集成 jwt 相关模块时此参数才会生效
* @return 对象自身
*/
public SaTokenConfig setJwtSecretKey(String jwtSecretKey) {
@@ -459,14 +515,14 @@ public class SaTokenConfig implements Serializable {
}
/**
* @return Http Basic 认证的账号和密码
* @return Http Basic 认证的默认账号和密码
*/
public String getBasic() {
return basic;
}
/**
* @param basic Http Basic 认证的账号和密码
* @param basic Http Basic 认证的默认账号和密码
* @return 对象自身
*/
public SaTokenConfig setBasic(String basic) {
@@ -577,6 +633,7 @@ public class SaTokenConfig implements Serializable {
+ ", isLog=" + isLog
+ ", logLevel=" + logLevel
+ ", logLevelInt=" + logLevelInt
+ ", isColorLog=" + isColorLog
+ ", jwtSecretKey=" + jwtSecretKey
+ ", basic=" + basic
+ ", currDomain=" + currDomain
@@ -13,10 +13,10 @@ import cn.dev33.satoken.util.SaFoxUtil;
/**
* Sa-Token配置文件的构建工厂类
* <p>
* 用于手动读取配置文件初始化 SaTokenConfig 对象,只有在非IOC环境下你才会用到此类
*
* <p> 用于手动读取配置文件初始化 SaTokenConfig 对象,只有在非IOC环境下你才会用到此类 </p>
*
* @author kong
* @author click33
* @since 2022-10-30
*/
public class SaTokenConfigFactory {
@@ -30,7 +30,7 @@ public class SaTokenConfigFactory {
public static String configPath = "sa-token.properties";
/**
* 根据configPath路径获取配置信息
* 根据 configPath 路径获取配置信息
*
* @return 一个SaTokenConfig对象
*/
@@ -42,7 +42,7 @@ public class SaTokenConfigFactory {
* 根据指定路径路径获取配置信息
*
* @param path 配置文件路径
* @return 一个SaTokenConfig对象
* @return 一个 SaTokenConfig 对象
*/
public static SaTokenConfig createConfig(String path) {
Map<String, String> map = readPropToMap(path);
@@ -7,52 +7,58 @@ import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.context.model.SaStorage;
/**
* Sa-Token 上下文持有类
* @author kong
* Sa-Token 上下文持有类,你可以通过此类快速获取当前环境下的 SaRequest、SaResponse、SaStorage、SaApplication 对象。
*
* @author click33
* @since <= 1.34.0
*/
public class SaHolder {
/**
* 获取当前请求的 SaTokenContext
* 获取当前请求的 SaTokenContext 上下文对象
* @see SaTokenContext
*
* @return see note
* @return /
*/
public static SaTokenContext getContext() {
return SaManager.getSaTokenContextOrSecond();
}
/**
* 获取当前请求的 [Request] 对象
* 获取当前请求的 Request 包装对象
* @see SaRequest
*
* @return see note
* @return /
*/
public static SaRequest getRequest() {
return SaManager.getSaTokenContextOrSecond().getRequest();
}
/**
* 获取当前请求的 [Response] 对象
* 获取当前请求的 Response 包装对象
* @see SaResponse
*
* @return see note
* @return /
*/
public static SaResponse getResponse() {
return SaManager.getSaTokenContextOrSecond().getResponse();
}
/**
* 获取当前请求的 [存储器] 对象
*
* @return see note
* 获取当前请求的 Storage 包装对象
* @see SaStorage
*
* @return /
*/
public static SaStorage getStorage() {
return SaManager.getSaTokenContextOrSecond().getStorage();
}
/**
* 获取全局 SaApplication 对象
* 获取全局 SaApplication 对象
* @see SaApplication
*
* @return see note
* @return /
*/
public static SaApplication getApplication() {
return SaApplication.defaultInstance;
@@ -6,43 +6,56 @@ import cn.dev33.satoken.context.model.SaResponse;
/**
* Sa-Token 上下文处理器
* @author kong
*
* <p> 上下文处理器封装了当前应用环境的底层操作,是 Sa-Token 对接不同 web 框架的关键,详细可参考在线文档 “自定义 SaTokenContext 指南”章节 </p>
*
* @author click33
* @since <= 1.34.0
*/
public interface SaTokenContext {
/**
* 获取当前请求的 [Request] 对象
* 获取当前请求的 Request 包装对象
* @see SaRequest
*
* @return see note
* @return /
*/
public SaRequest getRequest();
/**
* 获取当前请求的 [Response] 对象
* 获取当前请求的 Response 包装对象
* @see SaResponse
*
* @return see note
* @return /
*/
public SaResponse getResponse();
/**
* 获取当前请求的 [存储器] 对象
* 获取当前请求的 Storage 包装对象
* @see SaStorage
*
* @return see note
* @return /
*/
public SaStorage getStorage();
/**
* 校验指定路由匹配符是否可以匹配成功指定路径
* 判断:指定路由匹配符是否可以匹配成功指定路径
* <pre>
* 判断规则由底层 web 框架决定,例如在 springboot 中:
* - matchPath("/user/*", "/user/login") 返回: true
* - matchPath("/user/*", "/article/edit") 返回: false
* </pre>
*
* @param pattern 路由匹配符
* @param path 需要匹配的路径
* @return see note
* @return /
*/
public boolean matchPath(String pattern, String path);
/**
* 此上下文是否有效
* 判断:在本次请求中,此上下文是否可用。
* <p> 例如在部分 rpc 调用时, 一级上下文会返回 false,这时候框架就会选择使用二级上下文来处理请求 </p>
*
* @return /
*/
public default boolean isValid() {
@@ -7,15 +7,15 @@ import cn.dev33.satoken.error.SaErrorCode;
import cn.dev33.satoken.exception.InvalidContextException;
/**
* Sa-Token 上下文处理器 [默认实现类]
* Sa-Token 上下文处理器 [ 默认实现类 ]
*
* <p>
* 一般情况下框架会为你自动注入合适的上下文处理器,如果代码断点走到了此默认实现类,
* 说明你引入的依赖有问题或者错误的调用了Sa-Token的API, 请在[在线开发文档 → 附录 → 常见问题排查] 中按照提示进行排查
* 一般情况下框架会为你自动注入合适的上下文处理器,如果代码断点走到了此默认实现类,
* 说明你引入的依赖有问题或者错误的调用了 Sa-Token 的API 请在 [ 在线开发文档 → 附录 → 常见问题排查 ] 中按照提示进行排查
* </p>
*
* @author kong
*
* @author click33
* @since <= 1.34.0
*/
public class SaTokenContextDefaultImpl implements SaTokenContext {
@@ -25,37 +25,25 @@ public class SaTokenContextDefaultImpl implements SaTokenContext {
public static SaTokenContextDefaultImpl defaultContext = new SaTokenContextDefaultImpl();
/**
* 默认的错误提示语
* 错误提示语
*/
public static final String ERROR_MESSAGE = "未能获取有效的上下文处理器";
/**
* 获取当前请求的 [Request] 对象
*/
@Override
public SaRequest getRequest() {
throw new InvalidContextException(ERROR_MESSAGE).setCode(SaErrorCode.CODE_10001);
}
/**
* 获取当前请求的 [Response] 对象
*/
@Override
public SaResponse getResponse() {
throw new InvalidContextException(ERROR_MESSAGE).setCode(SaErrorCode.CODE_10001);
}
/**
* 获取当前请求的 [存储器] 对象
*/
@Override
public SaStorage getStorage() {
throw new InvalidContextException(ERROR_MESSAGE).setCode(SaErrorCode.CODE_10001);
}
/**
* 校验指定路由匹配符是否可以匹配成功指定路径
*/
@Override
public boolean matchPath(String pattern, String path) {
throw new InvalidContextException(ERROR_MESSAGE).setCode(SaErrorCode.CODE_10001);
@@ -5,15 +5,17 @@ import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.context.model.SaStorage;
/**
* Sa-Token 上下文处理器 [ThreadLocal版本]
* Sa-Token 上下文处理器 [ ThreadLocal 版本 ]
*
* <p>
* 使用 [ThreadLocal版本] 上下文处理器需要在全局过滤器或者拦截器内率先调用
* SaTokenContextForThreadLocalStorage.setBox(req,res, sto) 初始化上下文
* 使用 [ ThreadLocal 版本 ] 上下文处理器需要在全局过滤器或者拦截器内率先调用
* SaTokenContextForThreadLocalStorage.setBox(req, res, sto) 初始化上下文
* </p>
*
* @author kong
*
* <p> 一般情况下你不需要直接操作此类,因为框架的 starter 集成包里已经封装了完整的上下文操作 </p>
*
* @author click33
* @since <= 1.34.0
*/
public class SaTokenContextForThreadLocal implements SaTokenContext {
@@ -7,20 +7,22 @@ import cn.dev33.satoken.error.SaErrorCode;
import cn.dev33.satoken.exception.InvalidContextException;
/**
* Sa-Token 上下文处理器 [ThreadLocal版本] ---- 对象存储器
*
* @author kong
* Sa-Token 上下文处理器 [ThreadLocal 版本] ---- 对象存储器
*
* <p> 一般情况下你不需要直接操作此类,因为框架的 starter 集成包里已经封装了完整的上下文操作 </p>
*
* @author click33
* @since <= 1.34.0
*/
public class SaTokenContextForThreadLocalStorage {
/**
* 基于 ThreadLocal 的 [Box存储器]
* 基于 ThreadLocal 的 [ Box 存储器 ]
*/
public static ThreadLocal<Box> boxThreadLocal = new InheritableThreadLocal<Box>();
/**
* 初始化 [Box存储器]
* 初始化当前线程的 [ Box 存储器 ]
* @param request {@link SaRequest}
* @param response {@link SaResponse}
* @param storage {@link SaStorage}
@@ -31,23 +33,23 @@ public class SaTokenContextForThreadLocalStorage {
};
/**
* 清除 [Box存储器]
* 清除当前线程的 [ Box 存储器 ]
*/
public static void clearBox() {
boxThreadLocal.remove();
};
/**
* 获取 [Box存储器]
* @return see note
* 获取当前线程的 [ Box 存储器 ]
* @return /
*/
public static Box getBox() {
return boxThreadLocal.get();
};
/**
* 获取 [Box存储器], 如果为空则抛出异常
* @return see note
* 获取当前线程的 [ Box 存储器 ], 如果为空则抛出异常
* @return /
*/
public static Box getBoxNotNull() {
Box box = boxThreadLocal.get();
@@ -58,27 +60,27 @@ public class SaTokenContextForThreadLocalStorage {
};
/**
* 在 [Box存储器] 获取 [Request] 对象
* 在当前线程的 SaRequest 包装对象
*
* @return see note
* @return /
*/
public static SaRequest getRequest() {
return getBoxNotNull().getRequest();
}
/**
* 在 [Box存储器] 获取 [Response] 对象
* 在当前线程的 SaResponse 包装对象
*
* @return see note
* @return /
*/
public static SaResponse getResponse() {
return getBoxNotNull().getResponse();
}
/**
* 在 [Box存储器] 获取 [存储器] 对象
* 在当前线程的 SaStorage 存储器包装对象
*
* @return see note
* @return /
*/
public static SaStorage getStorage() {
return getBoxNotNull().getStorage();
@@ -86,11 +88,13 @@ public class SaTokenContextForThreadLocalStorage {
/**
* 临时内部类,用于存储[request、response、storage]三个对象
* @author kong
* Box 临时内部类,用于存储 [ SaRequest、SaResponse、SaStorage ] 三个包装对象
*
* @author click33
* @since <= 1.34.0
*/
/**
* @author kong
* @author click33
*
*/
public static class Box {
@@ -10,9 +10,10 @@ import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.util.SaFoxUtil;
/**
* Cookie Model
* @author kong
* Cookie Model,代表一个 Cookie 应该具有的所有参数
*
* @author click33
* @since <= 1.34.0
*/
public class SaCookie {
@@ -8,27 +8,28 @@ import java.util.List;
import java.util.Map;
/**
* Request 包装类
* @author kong
* Request 请求对象 包装类
*
* @author click33
* @since <= 1.34.0
*/
public interface SaRequest {
/**
* 获取底层源对象
* @return see note
* 获取底层被包装的源对象
* @return /
*/
public Object getSource();
/**
* 在 [请求体] 里获取一个值
* 在 [ 请求体 ] 里获取一个参数
* @param name 键
* @return 值
*/
public String getParam(String name);
/**
* 在 [请求体] 里获取一个值,值为空时返回默认值
* 在 [ 请求体 ] 里获取一个参数值,值为空时返回默认值
* @param name 键
* @param defaultValue 值为空时的默认值
* @return 值
@@ -42,7 +43,7 @@ public interface SaRequest {
}
/**
* 检测提供的参数是否为指定值
* 在 [ 请求体 ] 里检测提供的参数是否为指定值
* @param name 键
* @param value 值
* @return 是否相等
@@ -53,7 +54,7 @@ public interface SaRequest {
}
/**
* 检测请求是否提供了指定参数
* 在 [ 请求体 ] 里检测请求是否提供了指定参数
* @param name 参数名称
* @return 是否提供
*/
@@ -62,7 +63,7 @@ public interface SaRequest {
}
/**
* 在 [请求体] 里获取一个值 (此值必须存在,否则抛出异常 )
* 在 [ 请求体 ] 里获取一个值 (此值必须存在,否则抛出异常 )
* @param name 键
* @return 参数值
*/
@@ -75,26 +76,26 @@ public interface SaRequest {
}
/**
* 获取 [请求体] 里提交的所有参数名称
* 获取 [ 请求体 ] 里提交的所有参数名称
* @return 参数名称列表
*/
public List<String> getParamNames();
/**
* 获取 [请求体] 里提交的所有参数
* 获取 [ 请求体 ] 里提交的所有参数
* @return 参数列表
*/
public Map<String, String> getParamMap();
/**
* 在 [请求头] 里获取一个值
* 在 [ 请求头 ] 里获取一个值
* @param name 键
* @return 值
*/
public String getHeader(String name);
/**
* 在 [请求头] 里获取一个值
* 在 [ 请求头 ] 里获取一个值
* @param name 键
* @param defaultValue 值为空时的默认值
* @return 值
@@ -108,7 +109,7 @@ public interface SaRequest {
}
/**
* 在 [Cookie作用域] 里获取一个值
* 在 [ Cookie作用域 ] 里获取一个值
* @param name 键
* @return 值
*/
@@ -116,14 +117,14 @@ public interface SaRequest {
/**
* 返回当前请求path (不包括上下文名称)
* @return see note
* @return /
*/
public String getRequestPath();
/**
* 返回当前请求path是否为指定值
* 返回当前请求 path 是否为指定值
* @param path path
* @return see note
* @return /
*/
public default boolean isPath(String path) {
return getRequestPath().equals(path);
@@ -131,19 +132,19 @@ public interface SaRequest {
/**
* 返回当前请求的url,不带query参数,例:http://xxx.com/test
* @return see note
* @return /
*/
public String getUrl();
/**
* 返回当前请求的类型
* @return see note
* @return /
*/
public String getMethod();
/**
* 此请求是否为Ajax请求
* @return see note
* 判断此请求是否为 Ajax 异步请求
* @return /
*/
public default boolean isAjax() {
return getHeader("X-Requested-With") != null;
@@ -1,9 +1,10 @@
package cn.dev33.satoken.context.model;
/**
* Response 包装类
* @author kong
* Response 响应对象 包装类
*
* @author click33
* @since <= 1.34.0
*/
public interface SaResponse {
@@ -13,8 +14,8 @@ public interface SaResponse {
public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers";
/**
* 获取底层源对象
* @return see note
* 获取底层被包装的源对象
* @return /
*/
public Object getSource();
@@ -3,17 +3,18 @@ package cn.dev33.satoken.context.model;
import cn.dev33.satoken.application.SaSetValueInterface;
/**
* Storage Model,请求作用域的读取值对象
* <p> 在一次请求范围内: 存值、取值
*
* @author kong
* Storage Model,请求作用域的读取值对象
*
* <p> 在一次请求范围内: 存值、取值。数据在请求结束后失效。
*
* @author click33
* @since <= 1.34.0
*/
public interface SaStorage extends SaSetValueInterface {
/**
* 获取底层源对象
* @return see note
* 获取底层被包装的源对象
* @return /
*/
public Object getSource();
@@ -26,7 +27,7 @@ public interface SaStorage extends SaSetValueInterface {
/** 写值 */
@Override
public SaStorage set(String key, Object value);
/** 删值 */
@Override
public SaStorage delete(String key);
@@ -1,4 +1,5 @@
/**
* 因为不能确定最终运行的容器属于标准Servlet模型还是非Servlet模型,特封装此包下的包装类进行对接
* 因为不能确定最终运行的 web 容器属于标准 Servlet 模型还是非 Servlet 模型,特封装此包下的包装类进行对接
* 调用路径为:Sa-Token 功能函数 -> SaRequest 封装接口 -> SaRequest 具体实现类。
*/
package cn.dev33.satoken.context.model;
@@ -5,10 +5,12 @@ import cn.dev33.satoken.context.SaTokenContext;
/**
* Sa-Token 二级Context - 基础接口
*
* <p> (利用继承机制实现区别 [一级Context] 与 [二级Context] 的目的)
*
* @author kong
* <p> (利用继承机制实现区别 [ 一级Context ] 与 [ 二级Context ] 的目的)
*
* @see SaTokenContext SaTokenContext 上下文处理器
*
* @author click33
* @since <= 1.34.0
*/
public interface SaTokenSecondContext extends SaTokenContext {
@@ -3,14 +3,14 @@ package cn.dev33.satoken.context.second;
/**
* Sa-Token 二级Context - 创建器
*
* @author kong
*
* @author click33
* @since <= 1.34.0
*/
@FunctionalInterface
public interface SaTokenSecondContextCreator {
/**
* 创建一个二级 Context
* 创建一个二级 Context 处理器
* @return /
*/
public SaTokenSecondContext create();
@@ -1,163 +1,172 @@
package cn.dev33.satoken.dao;
import java.util.List;
import cn.dev33.satoken.session.SaSession;
import java.util.List;
/**
* Sa-Token持久层接口
* @author kong
* Sa-Token 持久层接口
*
* <p>
* 此接口的不同实现类可将数据存储至不同位置,如:内存Map、Redis 等等。
* 如果你要自定义数据存储策略,也需通过实现此接口来完成。
* </p>
*
* @author click33
* @since <= 1.34.0
*/
public interface SaTokenDao {
/** 常量,表示一个key永不过期 (在一个key被标注为永远不过期时返回此值) */
public static final long NEVER_EXPIRE = -1;
/** 常量,表示一个 key 永不过期 在一个 key 被标注为永远不过期时返回此值 */
long NEVER_EXPIRE = -1;
/** 常量,表示系统中不存在这个缓存 (在对不存在的key获取剩余存活时间时返回此值) */
public static final long NOT_VALUE_EXPIRE = -2;
/** 常量,表示系统中不存在这个缓存在对不存在的 key 获取剩余存活时间时返回此值 */
long NOT_VALUE_EXPIRE = -2;
// --------------------- 字符串读写 ---------------------
/**
* 获取Value,如无返空
* 获取 value,如无返空
*
* @param key 键名称
* @return value
*/
public String get(String key);
String get(String key);
/**
* 写入Value,并设定存活时间 (单位: 秒)
* 写入 value,并设定存活时间单位: 秒
*
* @param key 键名称
* @param value 值
* @param timeout 过期时间(值大于0时限时存储,值=-1时永久存储,值=0或小于-2时不存储)
* @param timeout 数据有效期(值大于0时限时存储,值=-1时永久存储,值=0或小于-2时不存储
*/
public void set(String key, String value, long timeout);
void set(String key, String value, long timeout);
/**
* 更新Value (过期时间不变)
* 更新 value 过期时间不变
* @param key 键名称
* @param value 值
*/
public void update(String key, String value);
void update(String key, String value);
/**
* 删除Value
* 删除 value
* @param key 键名称
*/
public void delete(String key);
void delete(String key);
/**
* 获取Value的剩余存活时间 (单位: 秒)
* @param key 指定key
* @return 这个key的剩余存活时间
* 获取 value 的剩余存活时间单位: 秒
* @param key 指定 key
* @return 这个 key 的剩余存活时间
*/
public long getTimeout(String key);
long getTimeout(String key);
/**
* 修改Value的剩余存活时间 (单位: 秒)
* @param key 指定key
* @param timeout 过期时间
* 修改 value 的剩余存活时间单位: 秒
* @param key 指定 key
* @param timeout 过期时间(单位: 秒)
*/
public void updateTimeout(String key, long timeout);
void updateTimeout(String key, long timeout);
// --------------------- 对象读写 ---------------------
/**
* 获取Object,如无返空
* 获取 Object,如无返空
* @param key 键名称
* @return object
*/
public Object getObject(String key);
Object getObject(String key);
/**
* 写入Object,并设定存活时间 (单位: 秒)
* 写入 Object,并设定存活时间 单位: 秒
* @param key 键名称
* @param object 值
* @param timeout 存活时间 (值大于0时限时存储,值=-1时永久存储,值=0或小于-2时不存储)
* @param timeout 存活时间值大于0时限时存储,值=-1时永久存储,值=0或小于-2时不存储
*/
public void setObject(String key, Object object, long timeout);
void setObject(String key, Object object, long timeout);
/**
* 更新Object (过期时间不变)
* 更新 Object 过期时间不变
* @param key 键名称
* @param object 值
*/
public void updateObject(String key, Object object);
void updateObject(String key, Object object);
/**
* 删除Object
* 删除 Object
* @param key 键名称
*/
public void deleteObject(String key);
void deleteObject(String key);
/**
* 获取Object的剩余存活时间 (单位: 秒)
* @param key 指定key
* @return 这个key的剩余存活时间
* 获取 Object 的剩余存活时间 单位: 秒
* @param key 指定 key
* @return 这个 key 的剩余存活时间
*/
public long getObjectTimeout(String key);
long getObjectTimeout(String key);
/**
* 修改Object的剩余存活时间 (单位: 秒)
* @param key 指定key
* @param timeout 过期时间
* 修改 Object 的剩余存活时间单位: 秒
* @param key 指定 key
* @param timeout 剩余存活时间
*/
public void updateObjectTimeout(String key, long timeout);
void updateObjectTimeout(String key, long timeout);
// --------------------- Session读写 ---------------------
// --------------------- SaSession 读写 (默认复用 Object 读写方法) ---------------------
/**
* 获取Session,如无返空
* 获取 SaSession,如无返空
* @param sessionId sessionId
* @return SaSession
*/
public default SaSession getSession(String sessionId) {
default SaSession getSession(String sessionId) {
return (SaSession)getObject(sessionId);
}
/**
* 写入Session,并设定存活时间 (单位: 秒)
* @param session 要保存的Session对象
* @param timeout 过期时间 (单位: 秒)
* 写入 SaSession,并设定存活时间单位: 秒
* @param session 要保存的 SaSession 对象
* @param timeout 过期时间单位: 秒
*/
public default void setSession(SaSession session, long timeout) {
default void setSession(SaSession session, long timeout) {
setObject(session.getId(), session, timeout);
}
/**
* 更新Session
* @param session 要更新的session对象
* 更新 SaSession
* @param session 要更新的 SaSession 对象
*/
public default void updateSession(SaSession session) {
default void updateSession(SaSession session) {
updateObject(session.getId(), session);
}
/**
* 删除Session
* 删除 SaSession
* @param sessionId sessionId
*/
public default void deleteSession(String sessionId) {
default void deleteSession(String sessionId) {
deleteObject(sessionId);
}
/**
* 获取Session剩余存活时间 (单位: 秒)
* @param sessionId 指定Session
* @return 这个Session的剩余存活时间
* 获取 SaSession 剩余存活时间单位: 秒
* @param sessionId 指定 SaSession
* @return 这个 SaSession 的剩余存活时间
*/
public default long getSessionTimeout(String sessionId) {
default long getSessionTimeout(String sessionId) {
return getObjectTimeout(sessionId);
}
/**
* 修改Session剩余存活时间 (单位: 秒)
* @param sessionId 指定Session
* @param timeout 过期时间
* 修改 SaSession 剩余存活时间单位: 秒
* @param sessionId 指定 SaSession
* @param timeout 剩余存活时间
*/
public default void updateSessionTimeout(String sessionId, long timeout) {
default void updateSessionTimeout(String sessionId, long timeout) {
updateObjectTimeout(sessionId, timeout);
}
@@ -169,12 +178,12 @@ public interface SaTokenDao {
* @param prefix 前缀
* @param keyword 关键字
* @param start 开始处索引
* @param size 获取数量 (-1代表从start处一直取到末尾)
* @param size 获取数量 (-1代表从 start 处一直取到末尾)
* @param sortType 排序类型(true=正序,false=反序)
*
* @return 查询到的数据集合
*/
public List<String> searchData(String prefix, String keyword, int start, int size, boolean sortType);
List<String> searchData(String prefix, String keyword, int start, int size, boolean sortType);
}
@@ -1,32 +1,32 @@
package cn.dev33.satoken.dao;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.util.SaFoxUtil;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.util.SaFoxUtil;
/**
* Sa-Token持久层接口 [默认实现类, 基于内存Map]
* @author kong
* Sa-Token 持久层接口默认实现类基于内存 Map,系统重启后数据丢失)
*
* @author click33
* @since <= 1.34.0
*/
public class SaTokenDaoDefaultImpl implements SaTokenDao {
/**
* 数据集合
* 存储数据集合
*/
public Map<String, Object> dataMap = new ConcurrentHashMap<String, Object>();
public Map<String, Object> dataMap = new ConcurrentHashMap<>();
/**
* 过期时间集合 (单位: 毫秒) , 记录所有key的到期时间 [注意不是剩余存活时间]
* 存储数据过期时间集合单位: 毫秒, 记录所有 key 的到期时间 注意存储的是到期时间,不是剩余存活时间
*/
public Map<String, Long> expireMap = new ConcurrentHashMap<String, Long>();
public Map<String, Long> expireMap = new ConcurrentHashMap<>();
/**
* 构造函数
*/
@@ -121,17 +121,30 @@ public class SaTokenDaoDefaultImpl implements SaTokenDao {
// ------------------------ Session 读写操作
// 使用接口默认实现
// ------------------------ 过期时间相关操作
// --------- 会话管理
@Override
public List<String> searchData(String prefix, String keyword, int start, int size, boolean sortType) {
return SaFoxUtil.searchList(expireMap.keySet(), prefix, keyword, start, size, sortType);
}
// ------------------------ 以下是一个定时缓存的简单实现,采用:惰性检查 + 异步循环扫描
// --------- 过期时间相关操作
/**
* 如果指定key已经过期,则立即清除它
* @param key 指定key
* 如果指定key 已经过期,则立即清除它
* @param key 指定 key
*/
void clearKeyByTimeout(String key) {
Long expirationTime = expireMap.get(key);
// 清除条件:如果不为空 && 不是[永不过期] && 已经超过过期时间
// 清除条件:
// 1、数据存在。
// 2、不是 [ 永不过期 ]。
// 3、已经超过过期时间。
if(expirationTime != null && expirationTime != SaTokenDao.NEVER_EXPIRE && expirationTime < System.currentTimeMillis()) {
dataMap.remove(key);
expireMap.remove(key);
@@ -139,23 +152,32 @@ public class SaTokenDaoDefaultImpl implements SaTokenDao {
}
/**
* 获取指定key的剩余存活时间 (单位:秒)
* 获取指定 key 的剩余存活时间 单位:秒
* @param key 指定 key
* @return 这个 key 的剩余存活时间
*/
long getKeyTimeout(String key) {
// 先检查是否已经过期
// 由于数据过期检测属于惰性扫描,很可能此时这个 key 已经过期状态了,所以这里需要先检查一下
clearKeyByTimeout(key);
// 获取过期时间
// 获取这个 key 的过期时间
Long expire = expireMap.get(key);
// 如果根本没有这个值
// 如果 expire 数据不存在,说明框架没有存储这个 key,此时返回 NOT_VALUE_EXPIRE
if(expire == null) {
return SaTokenDao.NOT_VALUE_EXPIRE;
}
// 如果被标注为永不过期
// 如果 expire 被标注为永不过期,则返回 NEVER_EXPIRE
if(expire == SaTokenDao.NEVER_EXPIRE) {
return SaTokenDao.NEVER_EXPIRE;
}
// ---- 计算剩余时间并返回
// ---- 代码至此,说明这个 key 是有过期时间的,且未过期,那么:
// 计算剩余时间并返回 (过期时间戳 - 当前时间戳) / 1000 转秒
long timeout = (expire - System.currentTimeMillis()) / 1000;
// 小于零时,视为不存在
if(timeout < 0) {
dataMap.remove(key);
@@ -164,12 +186,11 @@ public class SaTokenDaoDefaultImpl implements SaTokenDao {
}
return timeout;
}
// --------------------- 定时清理过期数据
// --------- 定时清理过期数据
/**
* 执行数据清理的线程
* 执行数据清理的线程引用
*/
public Thread refreshThread;
@@ -177,10 +198,9 @@ public class SaTokenDaoDefaultImpl implements SaTokenDao {
* 是否继续执行数据清理的线程标记
*/
public volatile boolean refreshFlag;
/**
* 清理所有已经过期的key
* 清理所有已经过期的 key
*/
public void refreshDataMap() {
Iterator<String> keys = expireMap.keySet().iterator();
@@ -190,14 +210,15 @@ public class SaTokenDaoDefaultImpl implements SaTokenDao {
}
/**
* 初始化定时任务
* 初始化定时任务,定时清理过期数据
*/
public void initRefreshThread() {
// 如果配置了<=0的值,则不启动定时清理
// 如果开发者配置了 <=0 的值,则不启动定时清理
if(SaManager.getConfig().getDataRefreshPeriod() <= 0) {
return;
}
// 启动定时刷新
this.refreshFlag = true;
this.refreshThread = new Thread(() -> {
@@ -228,27 +249,10 @@ public class SaTokenDaoDefaultImpl implements SaTokenDao {
}
/**
* 结束定时任务
* 结束定时任务,不再定时清理过期数据
*/
public void endRefreshThread() {
this.refreshFlag = false;
}
// --------------------- 会话管理
@Override
public List<String> searchData(String prefix, String keyword, int start, int size, boolean sortType) {
return SaFoxUtil.searchList(expireMap.keySet(), prefix, keyword, start, size, sortType);
}
}
@@ -3,167 +3,166 @@ package cn.dev33.satoken.error;
/**
* 定义所有异常细分状态码
*
* @author kong
* @since: 2022-10-30
* @author click33
* @since 2022-10-30
*/
public interface SaErrorCode {
/** 代表这个异常在抛出时未指定异常细分状态码 */
public static final int CODE_UNDEFINED = -1;
int CODE_UNDEFINED = -1;
// ------------
/** 未能获取有效的上下文处理器 */
public static final int CODE_10001 = 10001;
int CODE_10001 = 10001;
/** 未能获取有效的上下文 */
public static final int CODE_10002 = 10002;
int CODE_10002 = 10002;
/** JSON 转换器未实现 */
public static final int CODE_10003 = 10003;
int CODE_10003 = 10003;
/** 未能从全局 StpLogic 集合中找到对应 type 的 StpLogic */
public static final int CODE_10011 = 10011;
int CODE_10011 = 10011;
/** 指定的配置文件加载失败 */
public static final int CODE_10021 = 10021;
int CODE_10021 = 10021;
/** 配置文件属性无法正常读取 */
public static final int CODE_10022 = 10022;
int CODE_10022 = 10022;
/** 重置的侦听器集合不可以为空 */
public static final int CODE_10031 = 10031;
int CODE_10031 = 10031;
/** 注册的侦听器不可以为空 */
public static final int CODE_10032 = 10032;
int CODE_10032 = 10032;
// 1030x core模块
/** 提供的 Same-Token 是无效的 */
public static final int CODE_10301 = 10301;
int CODE_10301 = 10301;
/** 表示未能通过 Http Basic 认证校验 */
public static final int CODE_10311 = 10311;
int CODE_10311 = 10311;
/** 提供的 HttpMethod 是无效的 */
public static final int CODE_10321 = 10321;
int CODE_10321 = 10321;
// 1100x StpLogic
/** 未能读取到有效Token */
public static final int CODE_11001 = 11001;
int CODE_11001 = 11001;
/** 登录时的账号id值为空 */
public static final int CODE_11002 = 11002;
int CODE_11002 = 11002;
/** 更改 Token 指向的 账号Id 时,账号Id值为空 */
public static final int CODE_11003 = 11003;
int CODE_11003 = 11003;
/** 未能读取到有效Token */
public static final int CODE_11011 = 11011;
int CODE_11011 = 11011;
/** Token无效 */
public static final int CODE_11012 = 11012;
int CODE_11012 = 11012;
/** Token已过期 */
public static final int CODE_11013 = 11013;
int CODE_11013 = 11013;
/** Token已被顶下线 */
public static final int CODE_11014 = 11014;
int CODE_11014 = 11014;
/** Token已被踢下线 */
public static final int CODE_11015 = 11015;
int CODE_11015 = 11015;
/** Token已临时过期 */
public static final int CODE_11016 = 11016;
int CODE_11016 = 11016;
/** 在未集成 sa-token-jwt 插件时调用 getExtra() 抛出异常 */
public static final int CODE_11031 = 11031;
int CODE_11031 = 11031;
/** 缺少指定的角色 */
public static final int CODE_11041 = 11041;
int CODE_11041 = 11041;
/** 缺少指定的权限 */
public static final int CODE_11051 = 11051;
int CODE_11051 = 11051;
/** 当前账号未通过服务封禁校验 */
public static final int CODE_11061 = 11061;
int CODE_11061 = 11061;
/** 提供要解禁的账号无效 */
public static final int CODE_11062 = 11062;
int CODE_11062 = 11062;
/** 提供要解禁的服务无效 */
public static final int CODE_11063 = 11063;
int CODE_11063 = 11063;
/** 提供要解禁的等级无效 */
public static final int CODE_11064 = 11064;
int CODE_11064 = 11064;
/** 二级认证校验未通过 */
public static final int CODE_11071 = 11071;
int CODE_11071 = 11071;
// ------------
/** 请求中缺少指定的参数 */
public static final int CODE_12001 = 12001;
int CODE_12001 = 12001;
/** 构建 Cookie 时缺少 name 参数 */
public static final int CODE_12002 = 12002;
int CODE_12002 = 12002;
/** 构建 Cookie 时缺少 value 参数 */
public static final int CODE_12003 = 12003;
int CODE_12003 = 12003;
// ------------
/** Base64 编码异常 */
public static final int CODE_12101 = 12101;
int CODE_12101 = 12101;
/** Base64 解码异常 */
public static final int CODE_12102 = 12102;
int CODE_12102 = 12102;
/** URL 编码异常 */
public static final int CODE_12103 = 12103;
int CODE_12103 = 12103;
/** URL 解码异常 */
public static final int CODE_12104 = 12104;
int CODE_12104 = 12104;
/** md5 加密异常 */
public static final int CODE_12111 = 12111;
int CODE_12111 = 12111;
/** sha1 加密异常 */
public static final int CODE_12112 = 12112;
int CODE_12112 = 12112;
/** sha256 加密异常 */
public static final int CODE_12113 = 12113;
int CODE_12113 = 12113;
/** AES 加密异常 */
public static final int CODE_12114 = 12114;
int CODE_12114 = 12114;
/** AES 解密异常 */
public static final int CODE_12115 = 12115;
int CODE_12115 = 12115;
/** RSA 公钥加密异常 */
public static final int CODE_12116 = 12116;
int CODE_12116 = 12116;
/** RSA 私钥加密异常 */
public static final int CODE_12117 = 12117;
int CODE_12117 = 12117;
/** RSA 公钥解密异常 */
public static final int CODE_12118 = 12118;
int CODE_12118 = 12118;
/** RSA 私钥解密异常 */
public static final int CODE_12119 = 12119;
int CODE_12119 = 12119;
// ------------
/** 参与参数签名的秘钥不可为空 */
public static final int CODE_12201 = 12201;
int CODE_12201 = 12201;
/** 给定的签名无效 */
public static final int CODE_12202 = 12202;
int CODE_12202 = 12202;
/** timestamp 超出允许的范围 */
public static final int CODE_12203 = 12203;
int CODE_12203 = 12203;
}
@@ -1,8 +1,12 @@
package cn.dev33.satoken.exception;
/**
* 一个异常:代表 API 已被禁用
* @author kong
* 一个异常:代表 API 已被禁用
*
* <p> 一般在 API 不合适调用的时候抛出,例如在集成 jwt 模块后调用数据持久化相关方法 </p>
*
* @author click33
* @since <= 1.34.0
*/
public class ApiDisabledException extends SaTokenException {
@@ -1,9 +1,10 @@
package cn.dev33.satoken.exception;
/**
* 一个异常:代表停止匹配,直接退出,向前端输出结果
* 一个异常:代表停止匹配,直接退出,向前端输出结果 (框架内部专属异常,一般情况下开发者无需关注)
*
* @author kong
* @author click33
* @since <= 1.34.0
*/
public class BackResultException extends SaTokenException {
@@ -1,9 +1,10 @@
package cn.dev33.satoken.exception;
/**
* 一个异常:代表指定账号指定服务已被封禁
* 一个异常:代表指定账号指定服务已被封禁
*
* @author kong
* @author click33
* @since <= 1.34.0
*/
public class DisableServiceException extends SaTokenException {
@@ -1,25 +0,0 @@
package cn.dev33.satoken.exception;
/**
* <h1> 本类设计已过时,未来版本可能移除此类,请及时更换为 SameTokenInvalidException ,使用方式保持不变 </h1>
* 一个异常:代表提供的 Id-Token 无效
*
* @author kong
*/
@Deprecated
public class IdTokenInvalidException extends SaTokenException {
/**
* 序列化版本号
*/
private static final long serialVersionUID = 6806129545290130144L;
/**
* 一个异常:代表提供的 Id-Token 无效
* @param message 异常描述
*/
public IdTokenInvalidException(String message) {
super(message);
}
}
@@ -1,9 +1,9 @@
package cn.dev33.satoken.exception;
/**
* 一个异常:代表未能获取有效的上下文
* 一个异常:代表框架未能获取有效的上下文
*
* @author kong
* @author click33
* @since 2022-10-29
*/
public class InvalidContextException extends SaTokenException {
@@ -14,7 +14,7 @@ public class InvalidContextException extends SaTokenException {
private static final long serialVersionUID = 6806129545290130144L;
/**
* 一个异常:代表未能获取有效的上下文
* 一个异常:代表框架未能获取有效的上下文
* @param message 异常描述
*/
public InvalidContextException(String message) {
@@ -1,8 +1,10 @@
package cn.dev33.satoken.exception;
/**
* 一个异常:代表会话未能通过 Http Basic 认证
* @author kong
* 一个异常:代表会话未能通过 Http Basic 认证校验
*
* @author click33
* @since 2022-10-29
*/
public class NotBasicAuthException extends SaTokenException {
@@ -3,7 +3,7 @@ package cn.dev33.satoken.exception;
/**
* 一个异常:代表组件或方法未被提供有效的实现
*
* @author kong
* @author click33
* @since 2022-10-30
*/
public class NotImplException extends SaTokenException {
@@ -6,8 +6,10 @@ import java.util.List;
import cn.dev33.satoken.util.SaFoxUtil;
/**
* 一个异常:代表会话未能通过登录认证
* @author kong
* 一个异常:代表会话未能通过登录认证校验
*
* @author click33
* @since <= 1.34.0
*/
public class NotLoginException extends SaTokenException {
@@ -26,23 +28,23 @@ public class NotLoginException extends SaTokenException {
/** 表示未提供token */
public static final String NOT_TOKEN = "-1";
public static final String NOT_TOKEN_MESSAGE = "未能读取到有效Token";
public static final String NOT_TOKEN_MESSAGE = "未能读取到有效 token";
/** 表示token无效 */
public static final String INVALID_TOKEN = "-2";
public static final String INVALID_TOKEN_MESSAGE = "Token无效";
public static final String INVALID_TOKEN_MESSAGE = "token 无效";
/** 表示token已过期 */
public static final String TOKEN_TIMEOUT = "-3";
public static final String TOKEN_TIMEOUT_MESSAGE = "Token已过期";
public static final String TOKEN_TIMEOUT_MESSAGE = "token 已过期";
/** 表示token已被顶下线 */
public static final String BE_REPLACED = "-4";
public static final String BE_REPLACED_MESSAGE = "Token已被顶下线";
public static final String BE_REPLACED_MESSAGE = "token 已被顶下线";
/** 表示token已被踢下线 */
public static final String KICK_OUT = "-5";
public static final String KICK_OUT_MESSAGE = "Token已被踢下线";
public static final String KICK_OUT_MESSAGE = "token 已被踢下线";
/** 默认的提示语 */
public static final String DEFAULT_MESSAGE = "当前会话未登录";
@@ -3,10 +3,10 @@ package cn.dev33.satoken.exception;
import cn.dev33.satoken.stp.StpUtil;
/**
* 一个异常:代表会话未能通过权限认证
* 一个异常:代表会话未能通过权限认证校验
*
* @author kong
*
* @author click33
* @since <= 1.34.0
*/
public class NotPermissionException extends SaTokenException {
@@ -3,10 +3,10 @@ package cn.dev33.satoken.exception;
import cn.dev33.satoken.stp.StpUtil;
/**
* 一个异常:代表会话未能通过角色认证
* 一个异常:代表会话未能通过角色认证校验
*
* @author kong
*
* @author click33
* @since <= 1.34.0
*/
public class NotRoleException extends SaTokenException {
@@ -3,7 +3,8 @@ package cn.dev33.satoken.exception;
/**
* 一个异常:代表会话未能通过二级认证校验
*
* @author kong
* @author click33
* @since <= 1.34.0
*/
public class NotSafeException extends SaTokenException {
@@ -1,9 +1,9 @@
package cn.dev33.satoken.exception;
/**
* 一个异常:代表不是 Web 上下文
* 一个异常:代表当前不是 Web 上下文,无法调用某个 API
*
* @author kong
* @author click33
* @since 2022-10-29
*/
public class NotWebContextException extends SaTokenException {
@@ -14,7 +14,7 @@ public class NotWebContextException extends SaTokenException {
private static final long serialVersionUID = 6806129545290130144L;
/**
* 一个异常:代表不是 Web 上下文
* 一个异常:代表当前不是 Web 上下文,无法调用某个 API
* @param message 异常描述
*/
public NotWebContextException(String message) {
@@ -3,7 +3,8 @@ package cn.dev33.satoken.exception;
/**
* 一个异常:代表 JSON 转换失败
*
* @author kong
* @author click33
* @since <= 1.34.0
*/
public class SaJsonConvertException extends SaTokenException {
@@ -5,7 +5,7 @@ import cn.dev33.satoken.util.SaFoxUtil;
/**
* 一个异常:代表 API 参数签名校验失败
*
* @author kong
* @author click33
* @since 2023-5-3
*/
public class SaSignException extends SaTokenException {
@@ -4,11 +4,12 @@ import cn.dev33.satoken.error.SaErrorCode;
import cn.dev33.satoken.util.SaFoxUtil;
/**
* Sa-Token框架内部逻辑发生错误抛出的异常
* (自定义此异常方便开发者在做全局异常处理时分辨异常类型)
*
* @author kong
* Sa-Token 框架内部逻辑发生错误抛出的异常
*
* <p> 框架其它异常均继承自此类,开发者可通过捕获此异常来捕获框架内部抛出的所有异常 </p>
*
* @author click33
* @since <= 1.34.0
*/
public class SaTokenException extends RuntimeException {
@@ -1,9 +1,9 @@
package cn.dev33.satoken.exception;
/**
* 一个异常:代表提供的 Same-Token 无效
* 一个异常:代表 Same-Token 校验未通过
*
* @author kong
* @author click33
* @since 2022-10-24
*/
public class SameTokenInvalidException extends SaTokenException {
@@ -14,7 +14,7 @@ public class SameTokenInvalidException extends SaTokenException {
private static final long serialVersionUID = 6806129545290130144L;
/**
* 一个异常:代表提供的 Same-Token 无效
* 一个异常:代表 Same-Token 校验未通过
* @param message 异常描述
*/
public SameTokenInvalidException(String message) {
@@ -1,9 +1,10 @@
package cn.dev33.satoken.exception;
/**
* 一个异常:代表停止路由匹配,进入Controller
* 一个异常:代表停止路由匹配,进入 Controller (框架内部专属异常,一般情况下开发者无需关注)
*
* @author kong
* @author click33
* @since <= 1.34.0
*/
public class StopMatchException extends SaTokenException {
@@ -19,28 +19,28 @@ public interface SaFilter {
* @param paths 路由
* @return 对象自身
*/
public SaFilter addInclude(String... paths);
SaFilter addInclude(String... paths);
/**
* 添加 [ 放行路由 ]
* @param paths 路由
* @return 对象自身
*/
public SaFilter addExclude(String... paths);
SaFilter addExclude(String... paths);
/**
* 写入 [ 拦截路由 ] 集合
* @param pathList 路由集合
* @return 对象自身
*/
public SaFilter setIncludeList(List<String> pathList);
SaFilter setIncludeList(List<String> pathList);
/**
* 写入 [ 放行路由 ] 集合
* @param pathList 路由集合
* @return 对象自身
*/
public SaFilter setExcludeList(List<String> pathList);
SaFilter setExcludeList(List<String> pathList);
// ------------------------ 钩子函数
@@ -50,14 +50,14 @@ public interface SaFilter {
* @param auth see note
* @return 对象自身
*/
public SaFilter setAuth(SaFilterAuthStrategy auth);
SaFilter setAuth(SaFilterAuthStrategy auth);
/**
* 写入[ 异常处理函数 ]:每次[ 认证函数 ]发生异常时执行此函数
* @param error see note
* @return 对象自身
*/
public SaFilter setError(SaFilterErrorStrategy error);
SaFilter setError(SaFilterErrorStrategy error);
/**
* 写入[ 前置函数 ]:在每次[ 认证函数 ]之前执行。
@@ -65,6 +65,6 @@ public interface SaFilter {
* @param beforeAuth /
* @return 对象自身
*/
public SaFilter setBeforeAuth(SaFilterAuthStrategy beforeAuth);
SaFilter setBeforeAuth(SaFilterAuthStrategy beforeAuth);
}
@@ -1,16 +1,18 @@
package cn.dev33.satoken.filter;
/**
* Sa-Token全局过滤器-认证策略
* @author kong
* Sa-Token 全局过滤器 - 认证策略封装,方便 lambda 表达式风格调用
*
* @author click33
* @since <= 1.34.0
*/
@FunctionalInterface
public interface SaFilterAuthStrategy {
/**
* 执行方法
* @param r 无含义参数,留作扩展
* @param obj 无含义参数,留作扩展
*/
public void run(Object r);
void run(Object obj);
}
@@ -1,17 +1,21 @@
package cn.dev33.satoken.filter;
/**
* Sa-Token全局过滤器-异常处理策略
* @author kong
* Sa-Token 全局过滤器 - 异常处理策略封装,方便 lambda 表达式风格调用
*
* <p> 此方法的返回值将在 toString() 后返回给前端,如果你要返回 JSON 数据,需要在返回前自行序列化为 JSON 字符串 </p>
*
* @author click33
* @since <= 1.34.0
*/
@FunctionalInterface
public interface SaFilterErrorStrategy {
/**
* 执行方法
* @param e 异常对象
* @return 输出对象(请提前序列化)
* @return 输出对象,此返回值将在 toString() 后返回给前端,如果你要返回 JSON 数据,需要在返回前自行序列化为 JSON 字符串
*/
public Object run(Throwable e);
Object run(Throwable e);
}
@@ -1,10 +1,10 @@
package cn.dev33.satoken.fun;
/**
* 根据Boolean变量,决定是否执行一个函数
* lambda 表达式辅助封装:根据 Boolean 变量,决定是否执行一个函数
*
* @author kong
*
* @author click33
* @since <= 1.34.0
*/
public class IsRunFunction {
@@ -1,10 +1,10 @@
package cn.dev33.satoken.fun;
/**
* 设定一个函数,方便在Lambda表达式下的函数式编程
* 无形参、无返回值的函数式接口,方便开发者进行 lambda 表达式风格调用
*
* @author kong
*
* @author click33
* @since <= 1.34.0
*/
@FunctionalInterface
public interface SaFunction {
@@ -12,6 +12,6 @@ public interface SaFunction {
/**
* 执行的方法
*/
public void run();
void run();
}
@@ -4,7 +4,7 @@ import java.util.function.Function;
import java.util.function.Supplier;
/**
* 生成唯一式 token 的方法签名
* 生成唯一式 token 的函数式接口,方便开发者进行 lambda 表达式风格调用
*
* @author click33
* @since 2023/4/30
@@ -21,7 +21,7 @@ public interface SaGenerateUniqueTokenFunction {
* @param checkTokenFunction 校验 token 是否唯一的函数(返回 true 表示唯一,可用)
* @return 最终生成的唯一式 token
*/
public String execute(
String execute(
String elementName,
int maxTryTimes,
Supplier<String> createTokenFunction,
@@ -1,9 +1,10 @@
package cn.dev33.satoken.fun;
/**
* 设定一个函数,并传入一个参数,方便在Lambda表达式下的函数式编程
* @author kong
* 单形参、无返回值的函数式接口,方便开发者进行 lambda 表达式风格调用
*
* @author click33
* @since <= 1.34.0
*/
@FunctionalInterface
public interface SaParamFunction<T> {
@@ -12,6 +13,6 @@ public interface SaParamFunction<T> {
* 执行的方法
* @param r 传入的参数
*/
public void run(T r);
void run(T r);
}
@@ -1,9 +1,10 @@
package cn.dev33.satoken.fun;
/**
* 设定一个函数,传入一个参数,并返回一个值,方便在Lambda表达式下的函数式编程
* @author kong
* 单形参、有返回值的函数式接口,方便开发者进行 lambda 表达式风格调用
*
* @author click33
* @since <= 1.34.0
*/
@FunctionalInterface
public interface SaParamRetFunction<T, R> {
@@ -13,6 +14,6 @@ public interface SaParamRetFunction<T, R> {
* @param param 传入的参数
* @return 返回值
*/
public R run(T param);
R run(T param);
}
@@ -1,9 +1,10 @@
package cn.dev33.satoken.fun;
/**
* 设定一个函数,并返回一个值,方便在Lambda表达式下的函数式编程
* @author kong
* 无形参、有返回值的函数式接口,方便开发者进行 lambda 表达式风格调用
*
* @author click33
* @since <= 1.34.0
*/
@FunctionalInterface
public interface SaRetFunction {
@@ -12,6 +13,6 @@ public interface SaRetFunction {
* 执行的方法
* @return 返回值
*/
public Object run();
Object run();
}
@@ -0,0 +1,24 @@
package cn.dev33.satoken.fun;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.context.model.SaResponse;
/**
* 路由拦截器验证方法的函数式接口,方便开发者进行 lambda 表达式风格调用
*
* @author click33
* @since <= 1.34.0
*/
@FunctionalInterface
public interface SaRouteFunction {
/**
* 执行验证的方法
*
* @param request Request 包装对象
* @param response Response 包装对象
* @param handler 处理对象
*/
void run(SaRequest request, SaResponse response, Object handler);
}
@@ -5,24 +5,24 @@ import java.util.Map;
/**
* JSON 转换器
*
* @author kong
*
* @author click33
* @since <= 1.34.0
*/
public interface SaJsonTemplate {
/**
* 将任意对象转换为 json 字符串
* 将任意对象序列化为 json 字符串
*
* @param obj 对象
* @return 转换后的 json 字符串
*/
public String toJsonString(Object obj);
String toJsonString(Object obj);
/**
* 解析 json 字符串为map对象
* @param jsonStr json字符串
* @return map对象
* 解析 json 字符串为 map 对象
* @param jsonStr json 字符串
* @return map 对象
*/
public Map<String, Object> parseJsonToMap(String jsonStr);
Map<String, Object> parseJsonToMap(String jsonStr);
}
@@ -6,26 +6,22 @@ import cn.dev33.satoken.error.SaErrorCode;
import cn.dev33.satoken.exception.NotImplException;
/**
* JSON 相关操作接口
*
* @author kong
* JSON 转换器,默认实现类
*
* <p> 如果代码断点走到了此默认实现类,说明框架没有注入有效的 JSON 转换器,需要开发者自行实现并注入 </p>
*
* @author click33
* @since <= 1.34.0
*/
public class SaJsonTemplateDefaultImpl implements SaJsonTemplate {
public static final String ERROR_MESSAGE = "未实现具体的 json 转换器";
/**
* 将任意对象转换为 json 字符串
*/
@Override
public String toJsonString(Object obj) {
throw new NotImplException(ERROR_MESSAGE).setCode(SaErrorCode.CODE_10003);
}
/**
* 将 json 字符串解析为 Map
*/
@Override
public Map<String, Object> parseJsonToMap(String jsonStr) {
throw new NotImplException(ERROR_MESSAGE).setCode(SaErrorCode.CODE_10003);
@@ -11,8 +11,10 @@ import cn.dev33.satoken.stp.StpLogic;
/**
* Sa-Token 事件中心 事件发布器
*
* <p> 提供侦听器注册、事件发布能力 </p>
*
* @author kong
* @author click33
* @since: 2022-8-19
*/
public class SaTokenEventCenter {
@@ -127,7 +129,7 @@ public class SaTokenEventCenter {
// --------- 事件发布
/**
* 每次登录时触发
* 事件发布:xx 账号登录
* @param loginType 账号类别
* @param loginId 账号id
* @param tokenValue 本次登录产生的 token 值
@@ -140,7 +142,7 @@ public class SaTokenEventCenter {
}
/**
* 每次注销时触发
* 事件发布:xx 账号注销
* @param loginType 账号类别
* @param loginId 账号id
* @param tokenValue token值
@@ -152,7 +154,7 @@ public class SaTokenEventCenter {
}
/**
* 每次被踢下线时触发
* 事件发布:xx 账号被踢下线
* @param loginType 账号类别
* @param loginId 账号id
* @param tokenValue token值
@@ -164,7 +166,7 @@ public class SaTokenEventCenter {
}
/**
* 每次被顶下线时触发
* 事件发布:xx 账号被顶下线
* @param loginType 账号类别
* @param loginId 账号id
* @param tokenValue token值
@@ -176,7 +178,7 @@ public class SaTokenEventCenter {
}
/**
* 每次被封禁时触发
* 事件发布:xx 账号被封禁
* @param loginType 账号类别
* @param loginId 账号id
* @param service 指定服务
@@ -190,7 +192,7 @@ public class SaTokenEventCenter {
}
/**
* 每次被解封时触发
* 事件发布:xx 账号被解封
* @param loginType 账号类别
* @param loginId 账号id
* @param service 指定服务
@@ -202,7 +204,7 @@ public class SaTokenEventCenter {
}
/**
* 每次打开二级认证时触发
* 事件发布:xx 账号完成二级认证
* @param loginType 账号类别
* @param tokenValue token值
* @param service 指定服务
@@ -215,7 +217,7 @@ public class SaTokenEventCenter {
}
/**
* 每次关闭二级认证时触发
* 事件发布:xx 账号关闭二级认证
* @param loginType 账号类别
* @param service 指定服务
* @param tokenValue token值
@@ -227,7 +229,7 @@ public class SaTokenEventCenter {
}
/**
* 每次创建Session时触发
* 事件发布:创建了一个新的 SaSession
* @param id SessionId
*/
public static void doCreateSession(String id) {
@@ -237,7 +239,7 @@ public class SaTokenEventCenter {
}
/**
* 每次注销Session时触发
* 事件发布:一个 SaSession 注销了
* @param id SessionId
*/
public static void doLogoutSession(String id) {
@@ -247,7 +249,7 @@ public class SaTokenEventCenter {
}
/**
* 每次Token续期时触发
* 事件发布:指定 Token 续期成功
*
* @param tokenValue token 值
* @param loginId 账号id
@@ -259,9 +261,8 @@ public class SaTokenEventCenter {
}
}
/**
* 全局组件载入
* 事件发布:有新的全局组件载入到框架中
* @param compName 组件名称
* @param compObj 组件对象
*/
@@ -272,7 +273,7 @@ public class SaTokenEventCenter {
}
/**
* StpLogic 对象替换
* 事件发布:有新的 StpLogic 载入到框架中
* @param stpLogic /
*/
public static void doSetStpLogic(StpLogic stpLogic) {
@@ -282,7 +283,7 @@ public class SaTokenEventCenter {
}
/**
* 载入全局配置
* 事件发布:有新的全局配置载入到框架中
* @param config /
*/
public static void doSetConfig(SaTokenConfig config) {
@@ -6,9 +6,11 @@ import cn.dev33.satoken.stp.StpLogic;
/**
* Sa-Token 侦听器
* <p> 你可以通过实现此接口在用户登陆、退出等关键性操作时进行一些AOP操作
* @author kong
*
* <p> 你可以通过实现此接口在用户登录、退出等关键性操作时进行一些AOP切面操作 </p>
*
* @author click33
* @since <= 1.34.0
*/
public interface SaTokenListener {
@@ -19,7 +21,7 @@ public interface SaTokenListener {
* @param tokenValue 本次登录产生的 token 值
* @param loginModel 登录参数
*/
public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel);
void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel);
/**
* 每次注销时触发
@@ -27,7 +29,7 @@ public interface SaTokenListener {
* @param loginId 账号id
* @param tokenValue token值
*/
public void doLogout(String loginType, Object loginId, String tokenValue);
void doLogout(String loginType, Object loginId, String tokenValue);
/**
* 每次被踢下线时触发
@@ -35,7 +37,7 @@ public interface SaTokenListener {
* @param loginId 账号id
* @param tokenValue token值
*/
public void doKickout(String loginType, Object loginId, String tokenValue);
void doKickout(String loginType, Object loginId, String tokenValue);
/**
* 每次被顶下线时触发
@@ -43,7 +45,7 @@ public interface SaTokenListener {
* @param loginId 账号id
* @param tokenValue token值
*/
public void doReplaced(String loginType, Object loginId, String tokenValue);
void doReplaced(String loginType, Object loginId, String tokenValue);
/**
* 每次被封禁时触发
@@ -53,7 +55,7 @@ public interface SaTokenListener {
* @param level 封禁等级
* @param disableTime 封禁时长,单位: 秒
*/
public void doDisable(String loginType, Object loginId, String service, int level, long disableTime);
void doDisable(String loginType, Object loginId, String service, int level, long disableTime);
/**
* 每次被解封时触发
@@ -61,7 +63,7 @@ public interface SaTokenListener {
* @param loginId 账号id
* @param service 指定服务
*/
public void doUntieDisable(String loginType, Object loginId, String service);
void doUntieDisable(String loginType, Object loginId, String service);
/**
* 每次打开二级认证时触发
@@ -70,7 +72,7 @@ public interface SaTokenListener {
* @param service 指定服务
* @param safeTime 认证时间,单位:秒
*/
public void doOpenSafe(String loginType, String tokenValue, String service, long safeTime);
void doOpenSafe(String loginType, String tokenValue, String service, long safeTime);
/**
* 每次关闭二级认证时触发
@@ -78,46 +80,46 @@ public interface SaTokenListener {
* @param tokenValue token值
* @param service 指定服务
*/
public void doCloseSafe(String loginType, String tokenValue, String service);
void doCloseSafe(String loginType, String tokenValue, String service);
/**
* 每次创建Session时触发
* 每次创建 SaSession 时触发
* @param id SessionId
*/
public void doCreateSession(String id);
void doCreateSession(String id);
/**
* 每次注销Session时触发
* 每次注销 SaSession 时触发
* @param id SessionId
*/
public void doLogoutSession(String id);
void doLogoutSession(String id);
/**
* 每次Token续期时触发
* 每次 Token 续期时触发(注意:是 timeout 续期,而不是 activity-timeout 续期)
*
* @param tokenValue token 值
* @param loginId 账号id
* @param timeout 续期时间
*/
public void doRenewTimeout(String tokenValue, Object loginId, long timeout);
void doRenewTimeout(String tokenValue, Object loginId, long timeout);
/**
* 全局组件载入
* @param compName 组件名称
* @param compObj 组件对象
*/
public default void doRegisterComponent(String compName, Object compObj) {}
default void doRegisterComponent(String compName, Object compObj) {}
/**
* StpLogic 对象替换
* @param stpLogic /
*/
public default void doSetStpLogic(StpLogic stpLogic) {}
default void doSetStpLogic(StpLogic stpLogic) {}
/**
* 载入全局配置
* @param config /
*/
public default void doSetConfig(SaTokenConfig config) {}
default void doSetConfig(SaTokenConfig config) {}
}
@@ -8,9 +8,9 @@ import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.util.SaFoxUtil;
/**
* Sa-Token 侦听器实现:Log 打印
* Sa-Token 侦听器的一个实现:Log 打印
*
* @author kong
* @author click33
* @since 2022-11-2
*/
public class SaTokenListenerForLog implements SaTokenListener {
@@ -5,9 +5,9 @@ import cn.dev33.satoken.stp.SaLoginModel;
/**
* Sa-Token 侦听器,默认空实现
*
* <p> 对所有事件方法提供空实现,方便开发者通过继承此类快速实现一个可用的侦听器
* <p> 对所有事件方法提供空实现,方便开发者通过继承此类快速实现一个可用的侦听器 </p>
*
* @author kong
* @author click33
* @since: 2022-8-20
*/
public class SaTokenListenerForSimple implements SaTokenListener {
@@ -3,7 +3,7 @@ package cn.dev33.satoken.log;
/**
* Sa-Token 日志输出接口
*
* @author kong
* @author click33
* @since 2022-11-1
*/
public interface SaLog {
@@ -13,41 +13,41 @@ public interface SaLog {
* @param str 日志内容
* @param args 参数列表
*/
public void trace(String str, Object ...args);
void trace(String str, Object ...args);
/**
* 输出 debug 日志
* @param str 日志内容
* @param args 参数列表
*/
public void debug(String str, Object ...args);
void debug(String str, Object ...args);
/**
* 输出 info 日志
* @param str 日志内容
* @param args 参数列表
*/
public void info(String str, Object ...args);
void info(String str, Object ...args);
/**
* 输出 warn 日志
* @param str 日志内容
* @param args 参数列表
*/
public void warn(String str, Object ...args);
void warn(String str, Object ...args);
/**
* 输出 error 日志
* @param str 日志内容
* @param args 参数列表
*/
public void error(String str, Object ...args);
void error(String str, Object ...args);
/**
* 输出 fatal 日志
* @param str 日志内容
* @param args 参数列表
*/
public void fatal(String str, Object ...args);
void fatal(String str, Object ...args);
}
@@ -5,18 +5,13 @@ import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.util.StrFormatter;
/**
* Sa-Token 日志实现类 [控制台打印]
* Sa-Token 日志实现类 [ 控制台打印 ]
*
* @author kong
* @author click33
* @since 2022-11-1
*/
public class SaLogForConsole implements SaLog {
/**
* 日志输出的前缀
*/
public static String LOG_PREFIX = "SaLog -->: ";
/**
* 日志等级
*/
@@ -26,48 +21,107 @@ public class SaLogForConsole implements SaLog {
public static final int warn = 4;
public static final int error = 5;
public static final int fatal = 6;
/**
* 日志输出的前缀
*/
public static String LOG_PREFIX = "SaLog -->: ";
public static String TRACE_PREFIX = "SA [TRACE]-->: ";
public static String DEBUG_PREFIX = "SA [DEBUG]-->: ";
public static String INFO_PREFIX = "SA [INFO] -->: ";
public static String WARN_PREFIX = "SA [WARN] -->: ";
public static String ERROR_PREFIX = "SA [ERROR]-->: ";
public static String FATAL_PREFIX = "SA [FATAL]-->: ";
/**
* 日志输出的颜色
*/
public static String TRACE_COLOR = "\033[39m";
public static String DEBUG_COLOR = "\033[34m";
public static String INFO_COLOR = "\033[32m";
public static String WARN_COLOR = "\033[33m";
public static String ERROR_COLOR = "\033[31m";
public static String FATAL_COLOR = "\033[35m";
public static String DEFAULT_COLOR = "\033[39m";
@Override
public void trace(String str, Object... args) {
println(trace, str, args);
println(trace, TRACE_COLOR, TRACE_PREFIX, str, args);
}
@Override
public void debug(String str, Object... args) {
println(debug, str, args);
println(debug, DEBUG_COLOR, DEBUG_PREFIX, str, args);
}
@Override
public void info(String str, Object... args) {
println(info, str, args);
println(info, INFO_COLOR, INFO_PREFIX, str, args);
}
@Override
public void warn(String str, Object... args) {
println(warn, str, args);
println(warn, WARN_COLOR, WARN_PREFIX, str, args);
}
@Override
public void error(String str, Object... args) {
println(error, str, args);
println(error, ERROR_COLOR, ERROR_PREFIX, str, args);
}
@Override
public void fatal(String str, Object... args) {
println(fatal, str, args);
println(fatal, FATAL_COLOR, FATAL_PREFIX, str, args);
}
/**
* 打印日志到控制台
* @param level 日志等级
* @param level 日志等级
* @param color 颜色编码
* @param prefix 前缀
* @param str 字符串
* @param args 参数列表
*/
public void println(int level, String str, Object... args) {
public void println(int level, String color, String prefix, String str, Object... args) {
SaTokenConfig config = SaManager.getConfig();
if(config.getIsLog() && level >= config.getLogLevelInt()) {
System.out.println(LOG_PREFIX + StrFormatter.format(str, args));
if(config.getIsColorLog() == Boolean.TRUE) {
// 彩色日志
System.out.println(color + prefix + StrFormatter.format(str, args) + DEFAULT_COLOR);
} else {
// 黑白日志
System.out.println(prefix + StrFormatter.format(str, args));
}
}
}
/*
// 三种写法速度对比
// if( config.getIsColorLog() != null && config.getIsColorLog() ) 10亿次,2058ms
// if( config.getIsColorLog() == Boolean.TRUE ) 10亿次,1050ms 最快
// if( Objects.equals(config.getIsColorLog(), Boolean.TRUE) ) 10亿次,1543ms
*/
/*
颜色参考:
DEFAULT 39
BLACK 30
RED 31
GREEN 32
YELLOW 33
BLUE 34
MAGENTA 35
CYAN 36
WHITE 37
BRIGHT_BLACK 90
BRIGHT_RED 91
BRIGHT_GREEN 92
BRIGHT_YELLOW 93
BRIGHT_BLUE 94
BRIGHT_MAGENTA 95
BRIGHT_CYAN 96
BRIGHT_WHITE 97
*/
}
@@ -11,8 +11,8 @@ import cn.dev33.satoken.exception.SaTokenException;
*
* <p> 参考:Spring - HttpMethod
*
* @author kong
*
* @author click33
* @since <= 1.34.0
*/
public enum SaHttpMethod {
@@ -34,7 +34,7 @@ public enum SaHttpMethod {
/**
* String 转 enum
* @param method 请求类型
* @return ReqMethod 对象
* @return SaHttpMethod 对象
*/
public static SaHttpMethod toEnum(String method) {
if(method == null) {
@@ -50,7 +50,7 @@ public enum SaHttpMethod {
/**
* String[] 转 enum[]
* @param methods 请求类型数组
* @return ReqMethod 对象
* @return SaHttpMethod 数组
*/
public static SaHttpMethod[] toEnumArray(String... methods) {
SaHttpMethod [] arr = new SaHttpMethod[methods.length];
@@ -1,24 +0,0 @@
package cn.dev33.satoken.router;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.context.model.SaResponse;
/**
* 路由拦截器验证方法Lambda
*
* @author kong
*
*/
@FunctionalInterface
public interface SaRouteFunction {
/**
* 执行验证的方法
*
* @param request Request包装对象
* @param response Response包装对象
* @param handler 处理对象
*/
public void run(SaRequest request, SaResponse response, Object handler);
}
@@ -11,9 +11,20 @@ import cn.dev33.satoken.fun.SaParamFunction;
import cn.dev33.satoken.fun.SaParamRetFunction;
/**
* 路由匹配操作工具类
* @author kong
* 路由匹配操作工具类
*
* <p> 提供了一系列的路由匹配操作方法,一般用在全局拦截器、过滤器做路由拦截鉴权。 </p>
* <p> 简单示例: </p>
* <pre>
* // 指定一条 match 规则
* SaRouter
* .match("/**") // 拦截的 path 列表,可以写多个
* .notMatch("/user/doLogin") // 排除掉的 path 列表,可以写多个
* .check(r->StpUtil.checkLogin()); // 要执行的校验动作,可以写完整的 lambda 表达式
* </pre>
*
* @author click33
* @since <= 1.34.0
*/
public class SaRouter {
@@ -11,8 +11,8 @@ import cn.dev33.satoken.fun.SaParamRetFunction;
/**
* 路由匹配操作对象
*
* @author kong
*
* @author click33
* @since <= 1.34.0
*/
public class SaRouterStaff {
@@ -11,7 +11,7 @@ import cn.dev33.satoken.util.SaFoxUtil;
*
* <p> 解决同源系统互相调用时的身份认证校验, 例如:微服务网关请求转发鉴权、微服务RPC调用鉴权
*
* @author kong
* @author click33
* @since 2022-10-24
*/
public class SaSameTemplate {
@@ -7,7 +7,7 @@ import cn.dev33.satoken.SaManager;
*
* <p> 解决同源系统互相调用时的身份认证校验, 例如:微服务网关请求转发鉴权、微服务RPC调用鉴权
*
* @author kong
* @author click33
* @since 2022-10-24
*/
public class SaSameUtil {
@@ -7,9 +7,10 @@ import cn.dev33.satoken.error.SaErrorCode;
import cn.dev33.satoken.exception.SaTokenException;
/**
* Sa-Token Base64工具类
* @author kong
* Sa-Token Base64 工具类
*
* @author click33
* @since <= 1.34.0
*/
public class SaBase64Util {
@@ -29,8 +29,8 @@ import cn.dev33.satoken.exception.SaTokenException;
/**
* Sa-Token 常见加密算法工具类
*
* @author kong
*
* @author click33
* @since <= 1.34.0
*/
public class SaSecureUtil {
@@ -15,11 +15,20 @@ import cn.dev33.satoken.listener.SaTokenEventCenter;
import cn.dev33.satoken.util.SaFoxUtil;
/**
* Session Model,会话作用域的读取值对象
* <p> 在一次会话范围内: 存值、取值
* Session Model,会话作用域的读取值对象
*
* @author kong
* <p> 在一次会话范围内: 存值、取值。数据在注销登录后失效。</p>
* <p>
* 在 Sa-Token 中,SaSession 分为三种,分别是: <br>
* - Account-Session: 指的是框架为每个 账号id 分配的 SaSession。 <br>
* - Token-Session: 指的是框架为每个 token 分配的 SaSession。 <br>
* - Custom-Session: 指的是以一个 特定的值 作为SessionId,来分配的 SaSession。 <br>
* <br>
* 注意:以上分类仅为框架设计层面的概念区分,实际上它们的数据存储格式都是一致的。
* </p>
*
* @author click33
* @since <= 1.34.0
*/
public class SaSession implements SaSetValueInterface, Serializable {
@@ -2,9 +2,10 @@ package cn.dev33.satoken.session;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.util.SaTokenConsts;
/**
* 自定义 Session 工具类
* 自定义 SaSession 工具类,快捷的读取、操作自定义 SaSession
*
* <p>样例:
* <pre>
@@ -18,8 +19,8 @@ import cn.dev33.satoken.strategy.SaStrategy;
* System.out.println("count=" + count);
* </pre>
*
* @author kong
*
* @author click33
* @since <= 1.34.0
*/
public class SaSessionCustomUtil {
@@ -27,13 +28,13 @@ public class SaSessionCustomUtil {
}
/**
* 添加上指定前缀,防止恶意伪造Session
* 添加上指定前缀,防止恶意伪造数据
*/
public static String sessionKey = "custom";
/**
* 拼接Key: 自定义Session的Id
*
* 拼接Key: 在存储自定义 SaSession 时应该使用的 key
*
* @param sessionId 会话id
* @return sessionId
*/
@@ -42,9 +43,9 @@ public class SaSessionCustomUtil {
}
/**
* 指定keySession是否存在
* 判断:指定 key 的 SaSession 是否存在
*
* @param sessionId Sessionid
* @param sessionId SaSessionid
* @return 是否存在
*/
public static boolean isExists(String sessionId) {
@@ -52,35 +53,36 @@ public class SaSessionCustomUtil {
}
/**
* 获取指定keySession
* 获取指定 key 的 SaSession 对象, 如果此 SaSession 尚未在 DB 创建,isCreate 参数代表是否则新建并返回
*
* @param sessionId key
* @param isCreate 如果此Session尚未在DB创建,是否新建并返回
* @return SaSession
* @param sessionId SaSession 的 id
* @param isCreate 如果此 SaSession 尚未在 DB 创建,是否新建并返回
* @return SaSession 对象
*/
public static SaSession getSessionById(String sessionId, boolean isCreate) {
SaSession session = SaManager.getSaTokenDao().getSession(splicingSessionKey(sessionId));
if (session == null && isCreate) {
session = SaStrategy.me.createSession.apply(splicingSessionKey(sessionId));
session.setType(SaTokenConsts.SESSION_TYPE__CUSTOM);
SaManager.getSaTokenDao().setSession(session, SaManager.getConfig().getTimeout());
}
return session;
}
/**
* 获取指定keySession, 如果此Session尚未在DB创建,则新建并返回
* 获取指定 key 的 SaSession, 如果此 SaSession 尚未在 DB 创建,则新建并返回
*
* @param sessionId key
* @return session对象
* @param sessionId SaSession 的 id
* @return SaSession 对象
*/
public static SaSession getSessionById(String sessionId) {
return getSessionById(sessionId, true);
}
/**
* 删除指定keySession
* 删除指定 key 的 SaSession
*
* @param sessionId 指定key
* @param sessionId SaSession 的 id
*/
public static void deleteSessionById(String sessionId) {
SaManager.getSaTokenDao().deleteSession(splicingSessionKey(sessionId));
@@ -4,10 +4,11 @@ import java.io.Serializable;
/**
* Token 签名 Model
* <p>
* 挂在到 SaSession 上的 Token 签名
*
* @author kong
* <p> 挂在到 SaSession 上的 Token 签名,一般情况下,一个 TokenSign 代表一个登录的会话。</p>
*
* @author click33
* @since <= 1.34.0
*/
public class TokenSign implements Serializable {
@@ -12,9 +12,17 @@ import java.util.Map;
import java.util.TreeMap;
/**
* API 参数签名算法
* API 参数签名算法,在跨系统接口调用时防参数篡改、防重放攻击。
*
* @author kong
* <p>
* 以 SSO 数据拉取为例,流程大致如下:
* <br> 1. 以 md5( loginId={账号id}8nonce={随机字符串}8timestamp={13位时间戳}8key={secretkey秘钥} ) 生成签名 sign。
* <br> 2. 将 sign 作为参数,拼接到请求地址后面,如:http://xxx.com?loginId=100018nonce=xxx8timestamp=xxx8sign=xxx。
* <br> 3. 服务端接收到请求后,以同样的算法生成一次 sign 。
* <br> 4. 对比两次 sign 是否一致,一致则通过,否则拒绝 。
* </p>
*
* @author click33
* @since 2022-4-27
*/
public class SaSignTemplate {
@@ -35,6 +43,7 @@ public class SaSignTemplate {
* 获取:API 签名配置:
* 1. 如果用户自定义了 signConfig ,则使用用户自定义的。
* 2. 否则使用全局默认配置。
*
* @return /
*/
public SaSignConfig getSignConfigOrGlobal() {
@@ -136,6 +145,15 @@ public class SaSignTemplate {
// 计算签名
String paramsStr = joinParamsDictSort(paramsMap);
String fullStr = paramsStr + "&" + key + "=" + secretKey;
return abstractStr(fullStr);
}
/**
* 使用摘要算法创建签名
* @param fullStr 待摘要的字符串
* @return 签名
*/
public String abstractStr(String fullStr) {
return SaSecureUtil.md5(fullStr);
}
@@ -8,7 +8,7 @@ import java.util.Map;
/**
* API 参数签名算法 - 工具类
*
* @author kong
* @author click33
* @since 2022-4-27
*/
public class SaSignUtil {
@@ -3,11 +3,18 @@ package cn.dev33.satoken.stp;
import java.util.Map;
/**
*
* 快速构建 调用 `StpUtil.login()` 时的 [配置参数 Model ]
*
* @author kong
* 快速、简洁的构建:调用 `StpUtil.login()` 时的 [ 配置参数 SaLoginModel ]
*
* <pre>
* // 例如:在登录时指定 token 有效期为七天,代码如下:
* StpUtil.login(10001, SaLoginConfig.setTimeout(60 * 60 * 24 * 7));
*
* // 上面的代码与下面的代码等价
* StpUtil.login(10001, new SaLoginModel().setTimeout(60 * 60 * 24 * 7));
* </pre>
*
* @author click33
* @since <= 1.34.0
*/
public class SaLoginConfig {
@@ -9,9 +9,15 @@ import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.util.SaTokenConsts;
/**
* 调用 `StpUtil.login()` 时的 [配置参数 Model ]
* @author kong
* 调用 `StpUtil.login()` 时的 配置参数 Model,决定登录的一些细节行为 <br>
*
* <pre>
* // 例如:在登录时指定 token 有效期为七天,代码如下:
* StpUtil.login(10001, new SaLoginModel().setTimeout(60 * 60 * 24 * 7));
* </pre>
*
* @author click33
* @since <= 1.34.0
*/
public class SaLoginModel {
@@ -185,8 +191,8 @@ public class SaLoginModel {
+ "]";
}
// ------ 附加方法
/**
* 写入扩展数据(只在jwt模式下生效)
@@ -1,169 +1,187 @@
package cn.dev33.satoken.stp;
/**
* Token信息Model: 用来描述一个Token的常参数
*
* @author kong
* Token 信息 Model: 用来描述一个 Token 的常参数
*
* <p>
* 例如:<br>
* <pre>
* {
* "tokenName": "satoken", // token名称
* "tokenValue": "e67b99f1-3d7a-4a8d-bb2f-e888a0805633", // token值
* "isLogin": true, // 此token是否已经登录
* "loginId": "10001", // 此token对应的LoginId,未登录时为null
* "loginType": "login", // 账号类型标识
* "tokenTimeout": 2591977, // token剩余有效期 (单位: 秒)
* "sessionTimeout": 2591977, // User-Session剩余有效时间 (单位: 秒)
* "tokenSessionTimeout": -2, // Token-Session剩余有效时间 (单位: 秒) (-2表示系统中不存在这个缓存)
* "tokenActivityTimeout": -1, // token剩余无操作有效时间 (单位: 秒)
* "loginDevice": "default-device" // 登录设备类型
* }
* </pre>
* </p>
*
* @author click33
* @since <= 1.34.0
*/
public class SaTokenInfo {
/** token名称 */
/** token 名称 */
public String tokenName;
/** token值 */
/** token 值 */
public String tokenValue;
/** 此token是否已经登录 */
/** 此 token 是否已经登录 */
public Boolean isLogin;
/** 此token对应的LoginId,未登录时为null */
/** 此 token 对应的 LoginId,未登录时为 null */
public Object loginId;
/** 账号类型 */
/** 多账号体系下的账号类型 */
public String loginType;
/** token剩余有效期 (单位: 秒) */
/** token 剩余有效期单位: 秒 */
public long tokenTimeout;
/** User-Session剩余有效时间 (单位: 秒) */
/** Account-Session 剩余有效时间单位: 秒 */
public long sessionTimeout;
/** Token-Session剩余有效时间 (单位: 秒) */
/** Token-Session 剩余有效时间单位: 秒 */
public long tokenSessionTimeout;
/** token剩余无操作有效时间 (单位: 秒) */
/** token 剩余无操作有效时间单位: 秒 */
public long tokenActivityTimeout;
/** 登录设备类型 */
public String loginDevice;
/** 自定义数据 */
/** 自定义数据(暂无意义,留作扩展) */
public String tag;
/**
* @return token名称
* @return token 名称
*/
public String getTokenName() {
return tokenName;
}
/**
* @param tokenName token名称
* @param tokenName token 名称
*/
public void setTokenName(String tokenName) {
this.tokenName = tokenName;
}
/**
* @return token值
* @return token
*/
public String getTokenValue() {
return tokenValue;
}
/**
* @param tokenValue token值
* @param tokenValue token
*/
public void setTokenValue(String tokenValue) {
this.tokenValue = tokenValue;
}
/**
* @return 此token是否已经登录
* @return 此 token 是否已经登录
*/
public Boolean getIsLogin() {
return isLogin;
}
/**
* @param isLogin 此token是否已经登录
* @param isLogin 此 token 是否已经登录
*/
public void setIsLogin(Boolean isLogin) {
this.isLogin = isLogin;
}
/**
* @return 此token对应的LoginId,未登录时为null
* @return 此 token 对应的LoginId,未登录时为null
*/
public Object getLoginId() {
return loginId;
}
/**
* @param loginId 此token对应的LoginId,未登录时为null
* @param loginId 此 token 对应的LoginId,未登录时为null
*/
public void setLoginId(Object loginId) {
this.loginId = loginId;
}
/**
* @return 账号类型
* @return 多账号体系下的账号类型
*/
public String getLoginType() {
return loginType;
}
/**
* @param loginType 账号类型
* @param loginType 多账号体系下的账号类型
*/
public void setLoginType(String loginType) {
this.loginType = loginType;
}
/**
* @return token剩余有效期 (单位: 秒)
* @return token 剩余有效期单位: 秒
*/
public long getTokenTimeout() {
return tokenTimeout;
}
/**
* @param tokenTimeout token剩余有效期 (单位: 秒)
* @param tokenTimeout token剩余有效期单位: 秒
*/
public void setTokenTimeout(long tokenTimeout) {
this.tokenTimeout = tokenTimeout;
}
/**
* @return User-Session剩余有效时间 (单位: 秒)
* @return Account-Session 剩余有效时间单位: 秒
*/
public long getSessionTimeout() {
return sessionTimeout;
}
/**
* @param sessionTimeout User-Session剩余有效时间 (单位: 秒)
* @param sessionTimeout Account-Session剩余有效时间单位: 秒
*/
public void setSessionTimeout(long sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
/**
* @return Token-Session剩余有效时间 (单位: 秒)
* @return Token-Session剩余有效时间单位: 秒
*/
public long getTokenSessionTimeout() {
return tokenSessionTimeout;
}
/**
* @param tokenSessionTimeout Token-Session剩余有效时间 (单位: 秒)
* @param tokenSessionTimeout Token-Session剩余有效时间单位: 秒
*/
public void setTokenSessionTimeout(long tokenSessionTimeout) {
this.tokenSessionTimeout = tokenSessionTimeout;
}
/**
* @return token剩余无操作有效时间 (单位: 秒)
* @return token 剩余无操作有效时间单位: 秒
*/
public long getTokenActivityTimeout() {
return tokenActivityTimeout;
}
/**
* @param tokenActivityTimeout token剩余无操作有效时间 (单位: 秒)
* @param tokenActivityTimeout token 剩余无操作有效时间单位: 秒
*/
public void setTokenActivityTimeout(long tokenActivityTimeout) {
this.tokenActivityTimeout = tokenActivityTimeout;
@@ -184,14 +202,14 @@ public class SaTokenInfo {
}
/**
* @return 自定义数据
* @return 自定义数据(暂无意义,留作扩展)
*/
public String getTag() {
return tag;
}
/**
* @param tag 自定义数据
* @param tag 自定义数据(暂无意义,留作扩展)
*/
public void setTag(String tag) {
this.tag = tag;
@@ -208,7 +226,5 @@ public class SaTokenInfo {
+ ", tokenActivityTimeout=" + tokenActivityTimeout + ", loginDevice=" + loginDevice + ", tag=" + tag
+ "]";
}
}
@@ -3,9 +3,15 @@ package cn.dev33.satoken.stp;
import java.util.List;
/**
* 权限认证接口,实现此接口即可集成权限认证功能
* 权限数据加载源接口
*
* <p>
* 在使用权限校验 API 之前,你必须实现此接口,告诉框架哪些用户拥有哪些权限。<br>
* 框架默认不对数据进行缓存,如果你的数据是从数据库中读取的,一般情况下你需要手动实现数据的缓存读写。
* </p>
*
* @author kong
* @author click33
* @since <= 1.34.0
*/
public interface StpInterface {
@@ -6,9 +6,10 @@ import java.util.List;
/**
* 对 {@link StpInterface} 接口默认的实现类
* <p>
* 如果开发者没有实现StpInterface接口,则使用此默认实现
* 如果开发者没有实现 StpInterface 接口,则框架会使用此默认实现类,所有方法都返回空集合,即:用户不具有任何权限和角色。
*
* @author kong
* @author click33
* @since <= 1.34.0
*/
public class StpInterfaceDefaultImpl implements StpInterface {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -32,8 +32,8 @@ import java.util.function.Supplier;
});
* </pre>
*
* @author kong
*
* @author click33
* @since <= 1.34.0
*/
public final class SaStrategy {
@@ -49,37 +49,43 @@ public final class SaStrategy {
/**
* 创建 Token 的策略
* <p> 参数 [账号id, 账号类型]
* <p> 参数 [ 账号id, 账号类型 ]
*/
public BiFunction<Object, String, String> createToken = (loginId, loginType) -> {
// 根据配置的tokenStyle生成不同风格的token
String tokenStyle = SaManager.getConfig().getTokenStyle();
// uuid
if(SaTokenConsts.TOKEN_STYLE_UUID.equals(tokenStyle)) {
return UUID.randomUUID().toString();
switch (tokenStyle) {
// uuid
case SaTokenConsts.TOKEN_STYLE_UUID:
return UUID.randomUUID().toString();
// 简单uuid (不带下划线)
case SaTokenConsts.TOKEN_STYLE_SIMPLE_UUID:
return UUID.randomUUID().toString().replaceAll("-", "");
// 32位随机字符串
case SaTokenConsts.TOKEN_STYLE_RANDOM_32:
return SaFoxUtil.getRandomString(32);
// 64位随机字符串
case SaTokenConsts.TOKEN_STYLE_RANDOM_64:
return SaFoxUtil.getRandomString(64);
// 128位随机字符串
case SaTokenConsts.TOKEN_STYLE_RANDOM_128:
return SaFoxUtil.getRandomString(128);
// tik风格 (2_14_16)
case SaTokenConsts.TOKEN_STYLE_TIK:
return SaFoxUtil.getRandomString(2) + "_" + SaFoxUtil.getRandomString(14) + "_" + SaFoxUtil.getRandomString(16) + "__";
// 默认,还是uuid
default:
SaManager.getLog().warn("配置的 tokenStyle 值无效:{},仅允许以下取值: " +
"uuid、simple-uuid、random-32、random-64、random-128、tik", tokenStyle);
return UUID.randomUUID().toString();
}
// 简单uuid (不带下划线)
if(SaTokenConsts.TOKEN_STYLE_SIMPLE_UUID.equals(tokenStyle)) {
return UUID.randomUUID().toString().replaceAll("-", "");
}
// 32位随机字符串
if(SaTokenConsts.TOKEN_STYLE_RANDOM_32.equals(tokenStyle)) {
return SaFoxUtil.getRandomString(32);
}
// 64位随机字符串
if(SaTokenConsts.TOKEN_STYLE_RANDOM_64.equals(tokenStyle)) {
return SaFoxUtil.getRandomString(64);
}
// 128位随机字符串
if(SaTokenConsts.TOKEN_STYLE_RANDOM_128.equals(tokenStyle)) {
return SaFoxUtil.getRandomString(128);
}
// tik风格 (2_14_16)
if(SaTokenConsts.TOKEN_STYLE_TIK.equals(tokenStyle)) {
return SaFoxUtil.getRandomString(2) + "_" + SaFoxUtil.getRandomString(14) + "_" + SaFoxUtil.getRandomString(16) + "__";
}
// 默认,还是uuid
return UUID.randomUUID().toString();
};
/**
@@ -1,9 +1,10 @@
package cn.dev33.satoken.temp;
/**
* Sa-Token 临时令牌验证模块 默认实现类
* @author kong
* Sa-Token 临时令牌验证模块 默认实现类
*
* @author click33
* @since <= 1.34.0
*/
public class SaTempDefaultImpl implements SaTempInterface {
@@ -6,30 +6,37 @@ import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaTokenConsts;
/**
* Sa-Token 临时令牌验证模块接口
* @author kong
* Sa-Token 临时 token 验证模块 - 接口
*
* <p>
* 有效期很短的一种token,一般用于一次性接口防盗用、短时间资源访问等业务场景
* </p>
*
* @author click33
* @since <= 1.34.0
*/
public interface SaTempInterface {
// -------- 创建
/**
* 为 指定 创建一个临时 Token
* 为指定 value 创建一个临时 Token
* @param value 指定值
* @param timeout 有效,单位:秒,-1代表永久有效
* @return 生成的token
* @param timeout 有效时间,单位:秒,-1代表永久有效
* @return 生成的 token
*/
public default String createToken(Object value, long timeout) {
default String createToken(Object value, long timeout) {
return createToken(SaTokenConsts.DEFAULT_TEMP_TOKEN_SERVICE, value, timeout);
}
/**
* 为 指定服务 指定值 创建一个 Token
* @param service 务标识
* 为指定 业务标识、指定 value 创建一个 Token
* @param service 务标识
* @param value 指定值
* @param timeout 有效期,单位:秒,-1代表永久有效
* @return 生成的token
*/
public default String createToken(String service, Object value, long timeout) {
default String createToken(String service, Object value, long timeout) {
// 生成 token
String token = SaStrategy.me.createToken.apply(null, null);
@@ -41,23 +48,25 @@ public interface SaTempInterface {
// 返回
return token;
}
// -------- 解析
/**
* 解析 Token 获取 value
* @param token 指定 Token
* @return /
*/
public default Object parseToken(String token) {
default Object parseToken(String token) {
return parseToken(SaTokenConsts.DEFAULT_TEMP_TOKEN_SERVICE, token);
}
/**
* 解析 Token 获取 value
* @param service 务标识
* @param token 指定 Token
* @param service 务标识
* @param token 指定 Token
* @return /
*/
public default Object parseToken(String service, String token) {
default Object parseToken(String service, String token) {
String key = splicingKeyTempToken(service, token);
return SaManager.getSaTokenDao().getObject(key);
}
@@ -69,19 +78,19 @@ public interface SaTempInterface {
* @param <T> 默认值的类型
* @return /
*/
public default<T> T parseToken(String token, Class<T> cs) {
default<T> T parseToken(String token, Class<T> cs) {
return parseToken(SaTokenConsts.DEFAULT_TEMP_TOKEN_SERVICE, token, cs);
}
/**
* 解析 Token 获取 value,并转换为指定类型
* @param service 务标识
* @param service 务标识
* @param token 指定 Token
* @param cs 指定类型
* @param <T> 默认值的类型
* @return /
*/
public default<T> T parseToken(String service, String token, Class<T> cs) {
default<T> T parseToken(String service, String token, Class<T> cs) {
return SaFoxUtil.getValueByType(parseToken(service, token), cs);
}
@@ -91,54 +100,58 @@ public interface SaTempInterface {
* @param token 指定 Token
* @return /
*/
public default long getTimeout(String token) {
default long getTimeout(String token) {
return getTimeout(SaTokenConsts.DEFAULT_TEMP_TOKEN_SERVICE, token);
}
/**
* 获取指定服务指定 Token 的剩余有效期,单位:秒
* 获取指定 业务标识、指定 Token 的剩余有效期,单位:秒
* <p> 返回值 -1 代表永久,-2 代表token无效
* @param service 务标识
* @param service 务标识
* @param token 指定 Token
* @return /
*/
public default long getTimeout(String service, String token) {
default long getTimeout(String service, String token) {
String key = splicingKeyTempToken(service, token);
return SaManager.getSaTokenDao().getObjectTimeout(key);
}
// -------- 删除
/**
* 删除一个 Token
* @param token 指定 Token
*/
public default void deleteToken(String token) {
default void deleteToken(String token) {
deleteToken(SaTokenConsts.DEFAULT_TEMP_TOKEN_SERVICE, token);
}
/**
* 删除一个 Token
* @param service 务标识
* @param service 务标识
* @param token 指定 Token
*/
public default void deleteToken(String service, String token) {
default void deleteToken(String service, String token) {
String key = splicingKeyTempToken(service, token);
SaManager.getSaTokenDao().deleteObject(key);
}
// -------- 其它
/**
* 获取映射关系的持久化key
* @param service 务标识
* 获取:在存储临时 token 数据时,应该使用的 key
* @param service 务标识
* @param token token值
* @return key
*/
public default String splicingKeyTempToken(String service, String token) {
default String splicingKeyTempToken(String service, String token) {
return SaManager.getConfig().getTokenName() + ":temp-token:" + service + ":" + token;
}
/**
* @return jwt秘钥 (只有集成 sa-token-temp-jwt 模块时此参数才会生效)
*/
public default String getJwtSecretKey() {
default String getJwtSecretKey() {
return null;
}
@@ -3,17 +3,24 @@ package cn.dev33.satoken.temp;
import cn.dev33.satoken.SaManager;
/**
* Sa-Token 临时验证令牌模块
* @author kong
* Sa-Token 临时 token 验证模块 - 工具类
*
* <p>
* 有效期很短的一种token,一般用于一次性接口防盗用、短时间资源访问等业务场景
* </p>
*
* @author click33
* @since <= 1.34.0
*/
public class SaTempUtil {
private SaTempUtil() {
}
// -------- 创建
/**
* 为 指定 创建一个临时 Token
* 为指定 value 创建一个临时 Token
* @param value 指定值
* @param timeout 有效期,单位:秒,-1代表永久有效
* @return 生成的token
@@ -23,8 +30,8 @@ public class SaTempUtil {
}
/**
* 为 指定服务 指定值 创建一个 Token
* @param service 务标识
* 为指定 业务标识、指定 value 创建一个 Token
* @param service 务标识
* @param value 指定值
* @param timeout 有效期,单位:秒,-1代表永久有效
* @return 生成的token
@@ -33,6 +40,8 @@ public class SaTempUtil {
return SaManager.getSaTemp().createToken(service, value, timeout);
}
// -------- 解析
/**
* 解析 Token 获取 value
* @param token 指定 Token
@@ -44,7 +53,7 @@ public class SaTempUtil {
/**
* 解析 Token 获取 value
* @param service 务标识
* @param service 务标识
* @param token 指定 Token
* @return /
*/
@@ -65,7 +74,7 @@ public class SaTempUtil {
/**
* 解析 Token 获取 value,并转换为指定类型
* @param service 务标识
* @param service 务标识
* @param token 指定 Token
* @param cs 指定类型
* @param <T> 默认值的类型
@@ -86,9 +95,9 @@ public class SaTempUtil {
}
/**
* 获取指定服务指定 Token 的剩余有效期,单位:秒
* 获取指定 业务标识、指定 Token 的剩余有效期,单位:秒
* <p> 返回值 -1 代表永久,-2 代表token无效
* @param service 务标识
* @param service 务标识
* @param token 指定 Token
* @return /
*/
@@ -96,6 +105,8 @@ public class SaTempUtil {
return SaManager.getSaTemp().getTimeout(service, token);
}
// -------- 删除
/**
* 删除一个 Token
* @param token 指定 Token
@@ -106,7 +117,7 @@ public class SaTempUtil {
/**
* 删除一个 Token
* @param service 务标识
* @param service 务标识
* @param token 指定 Token
*/
public static void deleteToken(String service, String token) {
@@ -3,6 +3,7 @@ package cn.dev33.satoken.util;
import cn.dev33.satoken.error.SaErrorCode;
import cn.dev33.satoken.exception.SaTokenException;
import java.io.Console;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
@@ -18,8 +19,8 @@ import java.util.regex.Pattern;
/**
* Sa-Token 内部工具类
*
* @author kong
*
* @author click33
* @since <= 1.34.0
*/
public class SaFoxUtil {
@@ -75,7 +76,7 @@ public class SaFoxUtil {
* @return 是否为null或者空字符串
*/
public static boolean isNotEmpty(Object str) {
return isEmpty(str) == false;
return ! isEmpty(str);
}
/**
@@ -602,4 +603,39 @@ public class SaFoxUtil {
return logLevelList.get(level);
}
/**
* 判断当前系统是否可以打印彩色日志,判断准确率并非100%,但基本可以满足大部分场景
* @return /
*/
public static boolean isCanColorLog() {
// 获取当前环境相关信息
Console console = System.console();
String term = System.getenv().get("TERM");
// 两者均为 null,一般是在 eclipse、idea 等 IDE 环境下运行的,此时可以打印彩色日志
if(console == null && term == null) {
return true;
}
// 两者均不为 null,一般是在 linux 环境下控制台运行的,此时可以打印彩色日志
if(console != null && term != null) {
return true;
}
// console 有值,term 为 null,一般是在 windows 的 cmd 控制台运行的,此时不可以打印彩色日志
if(console != null && term == null) {
return false;
}
// console 为 nullterm 有值,一般是在 linux 的 nohup 命令运行的,此时不可以打印彩色日志
// 此时也有可能是在 windows 的 git bash 环境下运行的,此时可以打印彩色日志,但此场景无法和上述场景区分,所以统一不打印彩色日志
if(console == null && term != null) {
return false;
}
// 正常情况下,代码不会走到这里,但是方法又必须要有返回值,所以随便返回一个
return false;
}
}
@@ -5,19 +5,24 @@ import java.util.LinkedHashMap;
import java.util.Map;
/**
* 对 Ajax 请求返回Json格式数据的简易封装 <br>
* 所有预留字段:<br>
* code=状态码 <br>
* msg=描述信息 <br>
* data=携带对象 <br>
*
* @author kong
* 对请求接口返回 Json 格式数据的简易封装
*
* <p>
* 所有预留字段:<br>
* code = 状态码 <br>
* msg = 描述信息 <br>
* data = 携带对象 <br>
* </p>
*
* @author click33
* @since <= 1.34.0
*/
public class SaResult extends LinkedHashMap<String, Object> implements Serializable{
private static final long serialVersionUID = 1L; // 序列化版本号
// 序列化版本号
private static final long serialVersionUID = 1L;
// 预定的状态码
public static final int CODE_SUCCESS = 200;
public static final int CODE_ERROR = 500;
@@ -132,7 +137,7 @@ public class SaResult extends LinkedHashMap<String, Object> implements Serializa
}
// ============================ 构建 ==================================
// ============================ 静态方法快速构建 ==================================
// 构建成功
public static SaResult ok() {
@@ -182,6 +187,9 @@ public class SaResult extends LinkedHashMap<String, Object> implements Serializa
* @return
*/
private String transValue(Object value) {
if(value == null) {
return null;
}
if(value instanceof String) {
return "\"" + value + "\"";
}
@@ -1,9 +1,15 @@
package cn.dev33.satoken.util;
/**
* Sa-Token常量类
* @author kong
* Sa-Token 常量类
*
* <p>
* 一般的常量采用就近原则,定义在各自相应的模块中。
* 但有一些常量没有明确的归属模块,会在很多模块中使用到,比如版本号、开源地址等,属于全局性的础性常量,这些常量统一定义在此类中。
* </p>
*
* @author click33
* @since <= 1.34.0
*/
public class SaTokenConsts {
@@ -32,71 +38,72 @@ public class SaTokenConsts {
*/
public static final String DEV_DOC_URL = "https://sa-token.cc";
// ------------------ 常量key标记
// ------------------ 常量 key 标记
/**
* 常量key标记: 如果token为本次请求新创建的,则以此字符串为key存储在当前request中
* 常量 key 标记: 如果 token 为本次请求新创建的,则以此字符串为 key 存储在当前请求 str 中
*/
public static final String JUST_CREATED = "JUST_CREATED_";
/**
* 常量key标记: 如果token为本次请求新创建的,则以此字符串为key存储在当前request中(不拼接前缀,纯Token
* 常量 key 标记: 如果 token 为本次请求新创建的,则以此字符串为 key 存储在当前 request 中(不拼接前缀,纯Token
*/
public static final String JUST_CREATED_NOT_PREFIX = "JUST_CREATED_NOT_PREFIX_";
/**
* 常量key标记: 如果本次请求已经验证过[无操作过期], 则以此值存储在当前request中
* 常量 key 标记: 如果本次请求已经验证过 [ 临时过期 ] , 则以此值存储在当前 request
*/
public static final String TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY = "TOKEN_ACTIVITY_TIMEOUT_CHECKED_KEY_";
/**
* 常量key标记: 在登录时,默认使用的设备类型
* 常量 key 标记: 在登录时,默认使用的设备类型
*/
public static final String DEFAULT_LOGIN_DEVICE = "default-device";
/**
* 常量key标记: 在封禁账号时,默认封禁的服务类型
* 常量 key 标记: 在封禁账号时,默认封禁的服务类型
*/
public static final String DEFAULT_DISABLE_SERVICE = "login";
/**
* 常量key标记: 在封禁账号时,默认封禁的等级
* 常量 key 标记: 在封禁账号时,默认封禁的等级
*/
public static final int DEFAULT_DISABLE_LEVEL = 1;
/**
* 常量key标记: 在封禁账号时,可使用的最小封禁级别
* 常量 key 标记: 在封禁账号时,可使用的最小封禁级别
*/
public static final int MIN_DISABLE_LEVEL = 1;
/**
* 常量key标记: 账号封禁级别,表示未被封禁
* 常量 key 标记: 账号封禁级别,表示未被封禁
*/
public static final int NOT_DISABLE_LEVEL = -2;
/**
* 常量key标记: 在进行临时身份切换时使用的key
* 常量 key 标记: 在进行临时身份切换时使用的 key
*/
public static final String SWITCH_TO_SAVE_KEY = "SWITCH_TO_SAVE_KEY_";
/**
* 常量key标记: 在进行Token二级验证时,使用的key
* 常量 key 标记: 在进行 Token 二级验证时,使用的 key
*/
@Deprecated
public static final String SAFE_AUTH_SAVE_KEY = "SAFE_AUTH_SAVE_KEY_";
/**
* 常量key标记: 在进行 Token 二级证时,写入的 value 值
* 常量 key 标记: 在进行 Token 二级证时,写入的 value 值
*/
public static final String SAFE_AUTH_SAVE_VALUE = "SAFE_AUTH_SAVE_VALUE";
/**
* 常量key标记: 在进行 Token 二级验证时,默认的业务类型
* 常量 key 标记: 在进行 Token 二级验证时,默认的业务类型
*/
public static final String DEFAULT_SAFE_AUTH_SERVICE = "important";
/**
* 常量key标记: 临时 Token 认证模块,默认的业务类型
* 常量 key 标记: 临时 Token 认证模块,默认的业务类型
*/
public static final String DEFAULT_TEMP_TOKEN_SERVICE = "record";
@@ -155,7 +162,7 @@ public class SaTokenConsts {
// ------------------ 其它
/**
* 连接Token前缀和Token值的字符
* 连接 Token 前缀和 Token 值的字符
*/
public static final String TOKEN_CONNECTOR_CHAT = " ";
@@ -1,13 +1,14 @@
package cn.dev33.satoken.util;
/**
* 字符串格式化工具
* 字符串格式化工具,将字符串中的 {} 按序替换为参数
* <p>
* 本工具类 copy 自 Hutool
* https://github.com/dromara/hutool/blob/v5-master/hutool-core/src/main/java/cn/hutool/core/text/StrFormatter.java
* </p>
*
* @author Looly
* @since <= 1.34.0
*/
public class StrFormatter {
@@ -7,7 +7,7 @@ import cn.dev33.satoken.SaManager;
/**
* Sa-Token整合SpringBoot 示例
* @author kong
* @author click33
*
*/
@SpringBootApplication
@@ -10,7 +10,7 @@ import cn.dev33.satoken.stp.StpUtil;
/**
* 测试专用Controller
* @author kong
* @author click33
*
*/
@RestController
@@ -7,7 +7,7 @@ import cn.dev33.satoken.SaManager;
/**
* Sa-Token整合SpringBoot 示例
* @author kong
* @author click33
*
*/
@SpringBootApplication
@@ -10,7 +10,7 @@ import cn.dev33.satoken.stp.StpUtil;
/**
* 测试专用Controller
* @author kong
* @author click33
*
*/
@RestController

Some files were not shown because too many files have changed in this diff Show More