diff --git a/pom.xml b/pom.xml index 74aabede..8af0a3b3 100644 --- a/pom.xml +++ b/pom.xml @@ -21,8 +21,7 @@ sa-token-core sa-token-starter sa-token-plugin - - sa-token-demo/sa-token-demo-solon + diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/SaManager.java b/sa-token-core/src/main/java/cn/dev33/satoken/SaManager.java index 110e7b8b..9b9d1e38 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/SaManager.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/SaManager.java @@ -18,6 +18,8 @@ import cn.dev33.satoken.stp.StpInterface; import cn.dev33.satoken.stp.StpInterfaceDefaultImpl; import cn.dev33.satoken.stp.StpLogic; import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.temp.SaTempInterface; +import cn.dev33.satoken.temp.SaTempInterfaceDefaultImpl; import cn.dev33.satoken.util.SaFoxUtil; /** @@ -143,6 +145,24 @@ public class SaManager { return saTokenListener; } + /** + * 临时验证模块 Bean + */ + private static SaTempInterface saTemp; + public static void setSaTemp(SaTempInterface saTemp) { + SaManager.saTemp = saTemp; + } + public static SaTempInterface getSaTemp() { + if (saTemp == null) { + synchronized (SaManager.class) { + if (saTemp == null) { + setSaTemp(new SaTempInterfaceDefaultImpl()); + } + } + } + return saTemp; + } + /** * StpLogic集合, 记录框架所有成功初始化的StpLogic */ diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/session/SaSession.java b/sa-token-core/src/main/java/cn/dev33/satoken/session/SaSession.java index 84600efd..b9855a76 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/session/SaSession.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/session/SaSession.java @@ -9,6 +9,7 @@ import java.util.concurrent.ConcurrentHashMap; import cn.dev33.satoken.SaManager; import cn.dev33.satoken.fun.SaRetFunction; +import cn.dev33.satoken.util.SaFoxUtil; /** * Session Model @@ -401,7 +402,7 @@ public class SaSession implements Serializable { * @return 值 */ public T getModel(String key, Class cs) { - return getValueByClass(get(key), cs); + return SaFoxUtil.getValueByType(get(key), cs); } /** @@ -418,7 +419,7 @@ public class SaSession implements Serializable { if(valueIsNull(value)) { return (T)defaultValue; } - return getValueByClass(value, cs); + return SaFoxUtil.getValueByType(value, cs); } // ---- 其他 @@ -480,44 +481,6 @@ public class SaSession implements Serializable { return value == null || value.equals(""); } - /** - * 将指定值转化为指定类型 - * @param 泛型 - * @param obj 值 - * @param cs 类型 - * @return 转换后的值 - */ - @SuppressWarnings("unchecked") - protected T getValueByClass(Object obj, Class cs) { - // 如果 obj 本来就是 cs 类型 - if(obj != null && obj.getClass().equals(cs)) { - return (T)obj; - } - // 开始转换 - String obj2 = String.valueOf(obj); - Object obj3 = null; - if (cs.equals(String.class)) { - obj3 = obj2; - } else if (cs.equals(int.class) || cs.equals(Integer.class)) { - obj3 = Integer.valueOf(obj2); - } else if (cs.equals(long.class) || cs.equals(Long.class)) { - obj3 = Long.valueOf(obj2); - } else if (cs.equals(short.class) || cs.equals(Short.class)) { - obj3 = Short.valueOf(obj2); - } else if (cs.equals(byte.class) || cs.equals(Byte.class)) { - obj3 = Byte.valueOf(obj2); - } else if (cs.equals(float.class) || cs.equals(Float.class)) { - obj3 = Float.valueOf(obj2); - } else if (cs.equals(double.class) || cs.equals(Double.class)) { - obj3 = Double.valueOf(obj2); - } else if (cs.equals(boolean.class) || cs.equals(Boolean.class)) { - obj3 = Boolean.valueOf(obj2); - } else { - obj3 = (T)obj; - } - return (T)obj3; - } - /** * 根据默认值来获取值 * @param 泛型 @@ -535,7 +498,7 @@ public class SaSession implements Serializable { // 开始转换 Class cs = (Class) defaultValue.getClass(); - return getValueByClass(value, cs); + return SaFoxUtil.getValueByType(value, cs); } diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempInterface.java b/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempInterface.java new file mode 100644 index 00000000..e6135e22 --- /dev/null +++ b/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempInterface.java @@ -0,0 +1,72 @@ +package cn.dev33.satoken.temp; + +import cn.dev33.satoken.SaManager; +import cn.dev33.satoken.util.SaFoxUtil; + +/** + * Sa-Token 临时验证模块接口 + * @author kong + * + */ +public interface SaTempInterface { + + /** + * 根据value创建一个token + * @param value 指定值 + * @param time 有效期,单位:秒 + * @return 生成的token + */ + public default String createToken(Object value, long timeout) { + + // 生成 token + String token = SaManager.getSaTokenAction().createToken(null, null); + + // 持久化映射关系 + String key = splicingKeyTempToken(token); + SaManager.getSaTokenDao().setObject(key, value, timeout); + + // 返回 + return token; + } + + /** + * 解析token获取value + * @param token 指定token + * @return See Note + */ + public default Object parseToken(String token) { + String key = splicingKeyTempToken(token); + return SaManager.getSaTokenDao().getObject(key); + } + + /** + * 解析token获取value,并转换为指定类型 + * @param token 指定token + * @param cs 指定类型 + * @return See Note + */ + public default T parseToken(String token, Class cs) { + return SaFoxUtil.getValueByType(parseToken(token), cs); + } + + /** + * 返回指定token的剩余有效期,单位:秒 + *

返回值 -1 代表永久,-2 代表token无效 + * @param token see note + * @return see note + */ + public default long getTimeout(String token) { + String key = splicingKeyTempToken(token); + return SaManager.getSaTokenDao().getObjectTimeout(key); + } + + /** + * 获取映射关系的持久化key + * @param token token值 + * @return key + */ + public default String splicingKeyTempToken(String token) { + return SaManager.getConfig().getTokenName() + ":temp-token:" + token; + } + +} diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempInterfaceDefaultImpl.java b/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempInterfaceDefaultImpl.java new file mode 100644 index 00000000..ccf3ec95 --- /dev/null +++ b/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempInterfaceDefaultImpl.java @@ -0,0 +1,10 @@ +package cn.dev33.satoken.temp; + +/** + * Sa-Token 临时验证模块 逻辑 + * @author kong + * + */ +public class SaTempInterfaceDefaultImpl implements SaTempInterface { + +} diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempUtil.java b/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempUtil.java new file mode 100644 index 00000000..f5752d59 --- /dev/null +++ b/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempUtil.java @@ -0,0 +1,51 @@ +package cn.dev33.satoken.temp; + +import cn.dev33.satoken.SaManager; + +/** + * Sa-Token 临时验证模块 + * @author kong + * + */ +public class SaTempUtil { + + /** + * 根据value创建一个token + * @param value 指定值 + * @param time 有效期,单位:秒 + * @return 生成的token + */ + public static String createToken(Object value, long timeout) { + return SaManager.getSaTemp().createToken(value, timeout); + } + + /** + * 解析token获取value + * @param token 指定token + * @return See Note + */ + public static Object parseToken(String token) { + return SaManager.getSaTemp().parseToken(token); + } + + /** + * 解析token获取value,并转换为指定类型 + * @param token 指定token + * @param cs 指定类型 + * @return See Note + */ + public static T parseToken(String token, Class cs) { + return SaManager.getSaTemp().parseToken(token, cs); + } + + /** + * 返回指定token的剩余有效期,单位:秒 + *

返回值 -1 代表永久,-2 代表token无效 + * @param token see note + * @return see note + */ + public static long getTimeout(String token) { + return SaManager.getSaTemp().getTimeout(token); + } + +} diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/util/SaFoxUtil.java b/sa-token-core/src/main/java/cn/dev33/satoken/util/SaFoxUtil.java index e34d2835..73e2440d 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/util/SaFoxUtil.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/util/SaFoxUtil.java @@ -147,4 +147,44 @@ public class SaFoxUtil { return Pattern.matches(patt.replaceAll("\\*", ".*"), str); } + + /** + * 将指定值转化为指定类型 + * @param 泛型 + * @param obj 值 + * @param cs 类型 + * @return 转换后的值 + */ + @SuppressWarnings("unchecked") + public static T getValueByType(Object obj, Class cs) { + // 如果 obj 为 null 或者本来就是 cs 类型 + if(obj == null || obj.getClass().equals(cs)) { + return (T)obj; + } + // 开始转换 + String obj2 = String.valueOf(obj); + Object obj3 = null; + if (cs.equals(String.class)) { + obj3 = obj2; + } else if (cs.equals(int.class) || cs.equals(Integer.class)) { + obj3 = Integer.valueOf(obj2); + } else if (cs.equals(long.class) || cs.equals(Long.class)) { + obj3 = Long.valueOf(obj2); + } else if (cs.equals(short.class) || cs.equals(Short.class)) { + obj3 = Short.valueOf(obj2); + } else if (cs.equals(byte.class) || cs.equals(Byte.class)) { + obj3 = Byte.valueOf(obj2); + } else if (cs.equals(float.class) || cs.equals(Float.class)) { + obj3 = Float.valueOf(obj2); + } else if (cs.equals(double.class) || cs.equals(Double.class)) { + obj3 = Double.valueOf(obj2); + } else if (cs.equals(boolean.class) || cs.equals(Boolean.class)) { + obj3 = Boolean.valueOf(obj2); + } else { + obj3 = (T)obj; + } + return (T)obj3; + } + + } diff --git a/sa-token-doc/doc/use/config.md b/sa-token-doc/doc/use/config.md index 79d9b887..83d2945c 100644 --- a/sa-token-doc/doc/use/config.md +++ b/sa-token-doc/doc/use/config.md @@ -24,6 +24,8 @@ spring: is-share: false # token风格 token-style: uuid + # 是否输出操作日志 + is-log: false ``` 如果你习惯于 `application.properties` 类型的配置文件,那也很好办: 百度: [springboot properties与yml 配置文件的区别](https://www.baidu.com/s?ie=UTF-8&wd=springboot%20properties%E4%B8%8Eyml%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E7%9A%84%E5%8C%BA%E5%88%AB) @@ -48,6 +50,7 @@ public class SaTokenConfigure { config.setAllowConcurrentLogin(true); // 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) config.setIsShare(true); // 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) config.setTokenStyle("uuid"); // token风格 + config.setIsLog(false); // 是否输出操作日志 return config; } @@ -73,3 +76,4 @@ public class SaTokenConfigure { | autoRenew | Boolean | true | 是否打开自动续签 (如果此值为true, 框架会在每次直接或间接调用getLoginId()时进行一次过期检查与续签操作) | | tokenPrefix | Boolean | true | token前缀, 格式样例(satoken: Bearer xxxx-xxxx-xxxx-xxxx) [参考:token前缀](/use/token-prefix) | | isV | Boolean | true | 是否在初始化配置时打印版本字符画 | +| isLog | Boolean | false | 是否打印操作日志 | diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/SaTokenSpringBootStarterTest.java b/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/SaTokenSpringBootStarterTest.java index 9216abc6..38d03358 100644 --- a/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/SaTokenSpringBootStarterTest.java +++ b/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/SaTokenSpringBootStarterTest.java @@ -13,6 +13,7 @@ import org.springframework.test.context.junit4.SpringRunner; import cn.dev33.satoken.exception.DisableLoginException; import cn.dev33.satoken.session.SaSession; import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.temp.SaTempUtil; import cn.dev33.satoken.util.SaTokenConsts; /** @@ -126,6 +127,8 @@ public class SaTokenSpringBootStarterTest { session.set("age", "18"); Assert.assertEquals(session.get("name"), "zhang"); Assert.assertEquals(session.getInt("age"), 18); + Assert.assertEquals((int)session.getModel("age", int.class), 18); + Assert.assertEquals((int)session.get("age", 20), 18); Assert.assertEquals((int)session.get("name2", 20), 20); Assert.assertEquals((int)session.get("name2", () -> 30), 30); @@ -165,4 +168,21 @@ public class SaTokenSpringBootStarterTest { Assert.assertTrue(list.size() >= 5); } + // 测试:临时验证模块 + @Test + public void testSaTemp() { + // 生成token + String token = SaTempUtil.createToken("group-1014", 200); + Assert.assertNotNull(token); + + // 解析token + String value = SaTempUtil.parseToken(token, String.class); + System.out.println(value); + Assert.assertEquals(value, "group-1014"); + + // 过期时间 + long timeout = SaTempUtil.getTimeout(token); + Assert.assertTrue(timeout > 195); + } + }