mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-05-02 20:02:45 +08:00
新增token临时验证模块
This commit is contained in:
parent
6eec264e70
commit
bebee60901
3
pom.xml
3
pom.xml
@ -21,8 +21,7 @@
|
||||
<module>sa-token-core</module>
|
||||
<module>sa-token-starter</module>
|
||||
<module>sa-token-plugin</module>
|
||||
<!-- <module>sa-token-demo/sa-token-demo-springboot</module>-->
|
||||
<module>sa-token-demo/sa-token-demo-solon</module>
|
||||
<!-- <module>sa-token-demo/sa-token-demo-solon</module> -->
|
||||
</modules>
|
||||
|
||||
<!-- 开源协议 apache 2.0 -->
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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> T getModel(String key, Class<T> 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 <T> 泛型
|
||||
* @param obj 值
|
||||
* @param cs 类型
|
||||
* @return 转换后的值
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> T getValueByClass(Object obj, Class<T> 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 <T> 泛型
|
||||
@ -535,7 +498,7 @@ public class SaSession implements Serializable {
|
||||
|
||||
// 开始转换
|
||||
Class<T> cs = (Class<T>) defaultValue.getClass();
|
||||
return getValueByClass(value, cs);
|
||||
return SaFoxUtil.getValueByType(value, cs);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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> T parseToken(String token, Class<T> cs) {
|
||||
return SaFoxUtil.getValueByType(parseToken(token), cs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回指定token的剩余有效期,单位:秒
|
||||
* <p> 返回值 -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;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package cn.dev33.satoken.temp;
|
||||
|
||||
/**
|
||||
* Sa-Token 临时验证模块 逻辑
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaTempInterfaceDefaultImpl implements SaTempInterface {
|
||||
|
||||
}
|
@ -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> T parseToken(String token, Class<T> cs) {
|
||||
return SaManager.getSaTemp().parseToken(token, cs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回指定token的剩余有效期,单位:秒
|
||||
* <p> 返回值 -1 代表永久,-2 代表token无效
|
||||
* @param token see note
|
||||
* @return see note
|
||||
*/
|
||||
public static long getTimeout(String token) {
|
||||
return SaManager.getSaTemp().getTimeout(token);
|
||||
}
|
||||
|
||||
}
|
@ -147,4 +147,44 @@ public class SaFoxUtil {
|
||||
return Pattern.matches(patt.replaceAll("\\*", ".*"), str);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将指定值转化为指定类型
|
||||
* @param <T> 泛型
|
||||
* @param obj 值
|
||||
* @param cs 类型
|
||||
* @return 转换后的值
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T getValueByType(Object obj, Class<T> 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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 | 是否打印操作日志 |
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user