mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-12-21 10:59:45 +08:00
升级临时 Token 认证模块,可指定 service 参数。
This commit is contained in:
@@ -155,4 +155,15 @@ public interface SaErrorCode {
|
|||||||
/** RSA 私钥解密异常 */
|
/** RSA 私钥解密异常 */
|
||||||
public static final int CODE_12119 = 12119;
|
public static final int CODE_12119 = 12119;
|
||||||
|
|
||||||
|
// ------------
|
||||||
|
|
||||||
|
/** 参与参数签名的秘钥不可为空 */
|
||||||
|
public static final int CODE_12201 = 12201;
|
||||||
|
|
||||||
|
/** 给定的签名无效 */
|
||||||
|
public static final int CODE_12202 = 12202;
|
||||||
|
|
||||||
|
/** timestamp 超出允许的范围 */
|
||||||
|
public static final int CODE_12203 = 12203;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package cn.dev33.satoken.sign;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.error.SaErrorCode;
|
||||||
|
import cn.dev33.satoken.exception.SaTokenException;
|
||||||
import cn.dev33.satoken.secure.SaSecureUtil;
|
import cn.dev33.satoken.secure.SaSecureUtil;
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
|
|
||||||
@@ -15,15 +17,11 @@ import cn.dev33.satoken.util.SaFoxUtil;
|
|||||||
public interface SaSignTemplate {
|
public interface SaSignTemplate {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将所有参数连接成一个字符串
|
* 将所有参数连接成一个字符串(不排序),形如:b=2&a=1&c=3
|
||||||
* @param paramsMap 参数列表
|
* @param paramsMap 参数列表
|
||||||
* @return 字符串
|
* @return 拼接出的参数字符串
|
||||||
*/
|
*/
|
||||||
public default String joinParams(Map<String, Object> paramsMap) {
|
public default String joinParams(Map<String, Object> paramsMap) {
|
||||||
// 保证字段按照字典顺序排列
|
|
||||||
if(paramsMap instanceof TreeMap == false) {
|
|
||||||
paramsMap = new TreeMap<>(paramsMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 按照 k1=v1&k2=v2&k3=v3 排列
|
// 按照 k1=v1&k2=v2&k3=v3 排列
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
@@ -43,6 +41,21 @@ public interface SaSignTemplate {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将所有参数按照字典顺序连接成一个字符串,形如:a=1&b=2&c=3
|
||||||
|
* @param paramsMap 参数列表
|
||||||
|
* @return 拼接出的参数字符串
|
||||||
|
*/
|
||||||
|
public default String joinParamsDictSort(Map<String, Object> paramsMap) {
|
||||||
|
// 保证字段按照字典顺序排列
|
||||||
|
if(paramsMap instanceof TreeMap == false) {
|
||||||
|
paramsMap = new TreeMap<>(paramsMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拼接
|
||||||
|
return joinParams(paramsMap);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建签名:md5(paramsStr + keyStr)
|
* 创建签名:md5(paramsStr + keyStr)
|
||||||
* @param paramsMap 参数列表
|
* @param paramsMap 参数列表
|
||||||
@@ -50,10 +63,85 @@ public interface SaSignTemplate {
|
|||||||
* @return 签名
|
* @return 签名
|
||||||
*/
|
*/
|
||||||
public default String createSign(Map<String, Object> paramsMap, String key) {
|
public default String createSign(Map<String, Object> paramsMap, String key) {
|
||||||
String paramsStr = joinParams(paramsMap);
|
SaTokenException.throwByNull(key, "参与参数签名的秘钥不可为空", SaErrorCode.CODE_12201);
|
||||||
|
|
||||||
|
String paramsStr = joinParamsDictSort(paramsMap);
|
||||||
String fullStr = paramsStr + "&key=" + key;
|
String fullStr = paramsStr + "&key=" + key;
|
||||||
return SaSecureUtil.md5(fullStr);
|
return SaSecureUtil.md5(fullStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断:给定的参数 + 秘钥 生成的签名是否为有效签名
|
||||||
|
* @param paramsMap 参数列表
|
||||||
|
* @param key 秘钥
|
||||||
|
* @param sign 待验证的签名
|
||||||
|
* @return 签名是否有效
|
||||||
|
*/
|
||||||
|
public default boolean isValidSign(Map<String, Object> paramsMap, String key, String sign) {
|
||||||
|
String theSign = createSign(paramsMap, key);
|
||||||
|
return theSign.equals(sign);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验:给定的参数 + 秘钥 生成的签名是否为有效签名,如果签名无效则抛出异常
|
||||||
|
* @param paramsMap 参数列表
|
||||||
|
* @param key 秘钥
|
||||||
|
* @param sign 待验证的签名
|
||||||
|
*/
|
||||||
|
public default void checkSign(Map<String, Object> paramsMap, String key, String sign) {
|
||||||
|
if(isValidSign(paramsMap, key, sign) == false) {
|
||||||
|
throw new SaTokenException("无效签名:" + sign).setCode(SaErrorCode.CODE_12202);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给 paramsMap 追加 timestamp、nonce、sign 三个参数
|
||||||
|
* @param paramsMap 参数列表
|
||||||
|
* @param key 秘钥
|
||||||
|
* @return 加工后的参数列表
|
||||||
|
*/
|
||||||
|
public default Map<String, Object> addSignParams(Map<String, Object> paramsMap, String key) {
|
||||||
|
paramsMap.put("timestamp", String.valueOf(System.currentTimeMillis()));
|
||||||
|
paramsMap.put("nonce", SaFoxUtil.getRandomString(32));
|
||||||
|
paramsMap.put("sign", createSign(paramsMap, key));
|
||||||
|
return paramsMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给 paramsMap 追加 timestamp、nonce、sign 三个参数,并转换为参数字符串,形如:
|
||||||
|
* <code>data=xxx&nonce=xxx×tamp=xxx&sign=xxx</code>
|
||||||
|
* @param paramsMap 参数列表
|
||||||
|
* @param key 秘钥
|
||||||
|
* @return 加工后的参数列表 转化为的参数字符串
|
||||||
|
*/
|
||||||
|
public default String addSignParamsToString(Map<String, Object> paramsMap, String key) {
|
||||||
|
// 追加参数
|
||||||
|
paramsMap = addSignParams(paramsMap, key);
|
||||||
|
|
||||||
|
// .
|
||||||
|
return joinParams(paramsMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断:指定时间戳与当前时间戳的差距是否在允许的范围内
|
||||||
|
* @param timestamp 待校验的时间戳
|
||||||
|
* @param allowDisparity 允许的最大时间差(单位:ms),-1 代表不限制
|
||||||
|
* @return 是否在允许的范围内
|
||||||
|
*/
|
||||||
|
public default boolean isValidTimestamp(long timestamp, long allowDisparity) {
|
||||||
|
long disparity = Math.abs(System.currentTimeMillis() - timestamp);
|
||||||
|
return allowDisparity == -1 || disparity <= allowDisparity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验:指定时间戳与当前时间戳的差距是否在允许的范围内,如果超出则抛出异常
|
||||||
|
* @param timestamp 待校验的时间戳
|
||||||
|
* @param allowDisparity 允许的最大时间差(单位:ms),-1 代表不限制
|
||||||
|
*/
|
||||||
|
public default void checkTimestamp(long timestamp, long allowDisparity) {
|
||||||
|
if(isValidTimestamp(timestamp, allowDisparity) == false) {
|
||||||
|
throw new SaTokenException("timestamp 超出允许的范围:" + timestamp).setCode(SaErrorCode.CODE_12203);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package cn.dev33.satoken.temp;
|
|||||||
import cn.dev33.satoken.SaManager;
|
import cn.dev33.satoken.SaManager;
|
||||||
import cn.dev33.satoken.strategy.SaStrategy;
|
import cn.dev33.satoken.strategy.SaStrategy;
|
||||||
import cn.dev33.satoken.util.SaFoxUtil;
|
import cn.dev33.satoken.util.SaFoxUtil;
|
||||||
|
import cn.dev33.satoken.util.SaTokenConsts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sa-Token 临时令牌验证模块接口
|
* Sa-Token 临时令牌验证模块接口
|
||||||
@@ -12,18 +13,29 @@ import cn.dev33.satoken.util.SaFoxUtil;
|
|||||||
public interface SaTempInterface {
|
public interface SaTempInterface {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据value创建一个token
|
* 为 指定值 创建一个临时 Token
|
||||||
* @param value 指定值
|
* @param value 指定值
|
||||||
* @param timeout 有效期,单位:秒
|
* @param timeout 有效期,单位:秒,-1代表永久有效
|
||||||
* @return 生成的token
|
* @return 生成的token
|
||||||
*/
|
*/
|
||||||
public default String createToken(Object value, long timeout) {
|
public default String createToken(Object value, long timeout) {
|
||||||
|
return createToken(SaTokenConsts.DEFAULT_TEMP_TOKEN_SERVICE, value, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为 指定服务 指定值 创建一个 Token
|
||||||
|
* @param service 服务标识
|
||||||
|
* @param value 指定值
|
||||||
|
* @param timeout 有效期,单位:秒,-1代表永久有效
|
||||||
|
* @return 生成的token
|
||||||
|
*/
|
||||||
|
public default String createToken(String service, Object value, long timeout) {
|
||||||
|
|
||||||
// 生成 token
|
// 生成 token
|
||||||
String token = SaStrategy.me.createToken.apply(null, null);
|
String token = SaStrategy.me.createToken.apply(null, null);
|
||||||
|
|
||||||
// 持久化映射关系
|
// 持久化映射关系
|
||||||
String key = splicingKeyTempToken(token);
|
String key = splicingKeyTempToken(service, token);
|
||||||
SaManager.getSaTokenDao().setObject(key, value, timeout);
|
SaManager.getSaTokenDao().setObject(key, value, timeout);
|
||||||
|
|
||||||
// 返回
|
// 返回
|
||||||
@@ -31,43 +43,85 @@ public interface SaTempInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析token获取value
|
* 解析 Token 获取 value
|
||||||
* @param token 指定token
|
* @param token 指定 Token
|
||||||
* @return See Note
|
* @return /
|
||||||
*/
|
*/
|
||||||
public default Object parseToken(String token) {
|
public default Object parseToken(String token) {
|
||||||
String key = splicingKeyTempToken(token);
|
return parseToken(SaTokenConsts.DEFAULT_TEMP_TOKEN_SERVICE, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析 Token 获取 value
|
||||||
|
* @param service 服务标识
|
||||||
|
* @param token 指定 Token
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public default Object parseToken(String service, String token) {
|
||||||
|
String key = splicingKeyTempToken(service, token);
|
||||||
return SaManager.getSaTokenDao().getObject(key);
|
return SaManager.getSaTokenDao().getObject(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析token获取value,并转换为指定类型
|
* 解析 Token 获取 value,并转换为指定类型
|
||||||
* @param token 指定token
|
* @param token 指定 Token
|
||||||
* @param cs 指定类型
|
* @param cs 指定类型
|
||||||
* @param <T> 默认值的类型
|
* @param <T> 默认值的类型
|
||||||
* @return See Note
|
* @return /
|
||||||
*/
|
*/
|
||||||
public default<T> T parseToken(String token, Class<T> cs) {
|
public default<T> T parseToken(String token, Class<T> cs) {
|
||||||
return SaFoxUtil.getValueByType(parseToken(token), cs);
|
return parseToken(SaTokenConsts.DEFAULT_TEMP_TOKEN_SERVICE, token, cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析 Token 获取 value,并转换为指定类型
|
||||||
|
* @param service 服务标识
|
||||||
|
* @param token 指定 Token
|
||||||
|
* @param cs 指定类型
|
||||||
|
* @param <T> 默认值的类型
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public default<T> T parseToken(String service, String token, Class<T> cs) {
|
||||||
|
return SaFoxUtil.getValueByType(parseToken(service, token), cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取指定 token 的剩余有效期,单位:秒
|
* 获取指定 Token 的剩余有效期,单位:秒
|
||||||
* <p> 返回值 -1 代表永久,-2 代表token无效
|
* <p> 返回值 -1 代表永久,-2 代表token无效
|
||||||
* @param token see note
|
* @param token 指定 Token
|
||||||
* @return see note
|
* @return /
|
||||||
*/
|
*/
|
||||||
public default long getTimeout(String token) {
|
public default long getTimeout(String token) {
|
||||||
String key = splicingKeyTempToken(token);
|
return getTimeout(SaTokenConsts.DEFAULT_TEMP_TOKEN_SERVICE, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定服务指定 Token 的剩余有效期,单位:秒
|
||||||
|
* <p> 返回值 -1 代表永久,-2 代表token无效
|
||||||
|
* @param service 服务标识
|
||||||
|
* @param token 指定 Token
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public default long getTimeout(String service, String token) {
|
||||||
|
String key = splicingKeyTempToken(service, token);
|
||||||
return SaManager.getSaTokenDao().getObjectTimeout(key);
|
return SaManager.getSaTokenDao().getObjectTimeout(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除一个 token
|
* 删除一个 Token
|
||||||
* @param token 指定token
|
* @param token 指定 Token
|
||||||
*/
|
*/
|
||||||
public default void deleteToken(String token) {
|
public default void deleteToken(String token) {
|
||||||
String key = splicingKeyTempToken(token);
|
deleteToken(SaTokenConsts.DEFAULT_TEMP_TOKEN_SERVICE, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除一个 Token
|
||||||
|
* @param service 服务标识
|
||||||
|
* @param token 指定 Token
|
||||||
|
*/
|
||||||
|
public default void deleteToken(String service, String token) {
|
||||||
|
String key = splicingKeyTempToken(service, token);
|
||||||
SaManager.getSaTokenDao().deleteObject(key);
|
SaManager.getSaTokenDao().deleteObject(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,8 +130,8 @@ public interface SaTempInterface {
|
|||||||
* @param token token值
|
* @param token token值
|
||||||
* @return key
|
* @return key
|
||||||
*/
|
*/
|
||||||
public default String splicingKeyTempToken(String token) {
|
public default String splicingKeyTempToken(String service, String token) {
|
||||||
return SaManager.getConfig().getTokenName() + ":temp-token:" + token;
|
return SaManager.getConfig().getTokenName() + ":temp-token:" + service + ":" + token;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -11,53 +11,106 @@ public class SaTempUtil {
|
|||||||
|
|
||||||
private SaTempUtil() {
|
private SaTempUtil() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据value创建一个token
|
* 为 指定值 创建一个临时 Token
|
||||||
* @param value 指定值
|
* @param value 指定值
|
||||||
* @param timeout 有效期,单位:秒
|
* @param timeout 有效期,单位:秒,-1代表永久有效
|
||||||
* @return 生成的token
|
* @return 生成的token
|
||||||
*/
|
*/
|
||||||
public static String createToken(Object value, long timeout) {
|
public static String createToken(Object value, long timeout) {
|
||||||
return SaManager.getSaTemp().createToken(value, timeout);
|
return SaManager.getSaTemp().createToken(value, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析token获取value
|
* 为 指定服务 指定值 创建一个 Token
|
||||||
* @param token 指定token
|
* @param service 服务标识
|
||||||
* @return See Note
|
* @param value 指定值
|
||||||
|
* @param timeout 有效期,单位:秒,-1代表永久有效
|
||||||
|
* @return 生成的token
|
||||||
|
*/
|
||||||
|
public static String createToken(String service, Object value, long timeout) {
|
||||||
|
return SaManager.getSaTemp().createToken(service, value, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析 Token 获取 value
|
||||||
|
* @param token 指定 Token
|
||||||
|
* @return /
|
||||||
*/
|
*/
|
||||||
public static Object parseToken(String token) {
|
public static Object parseToken(String token) {
|
||||||
return SaManager.getSaTemp().parseToken(token);
|
return SaManager.getSaTemp().parseToken(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析token获取value,并转换为指定类型
|
* 解析 Token 获取 value
|
||||||
* @param token 指定token
|
* @param service 服务标识
|
||||||
|
* @param token 指定 Token
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static Object parseToken(String service, String token) {
|
||||||
|
return SaManager.getSaTemp().parseToken(service, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析 Token 获取 value,并转换为指定类型
|
||||||
|
* @param token 指定 Token
|
||||||
* @param cs 指定类型
|
* @param cs 指定类型
|
||||||
* @param <T> 默认值的类型
|
* @param <T> 默认值的类型
|
||||||
* @return See Note
|
* @return /
|
||||||
*/
|
*/
|
||||||
public static<T> T parseToken(String token, Class<T> cs) {
|
public static<T> T parseToken(String token, Class<T> cs) {
|
||||||
return SaManager.getSaTemp().parseToken(token, cs);
|
return SaManager.getSaTemp().parseToken(token, cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析 Token 获取 value,并转换为指定类型
|
||||||
|
* @param service 服务标识
|
||||||
|
* @param token 指定 Token
|
||||||
|
* @param cs 指定类型
|
||||||
|
* @param <T> 默认值的类型
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static<T> T parseToken(String service, String token, Class<T> cs) {
|
||||||
|
return SaManager.getSaTemp().parseToken(service, token, cs);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取指定 token 的剩余有效期,单位:秒
|
* 获取指定 Token 的剩余有效期,单位:秒
|
||||||
* <p> 返回值 -1 代表永久,-2 代表token无效
|
* <p> 返回值 -1 代表永久,-2 代表token无效
|
||||||
* @param token see note
|
* @param token 指定 Token
|
||||||
* @return see note
|
* @return /
|
||||||
*/
|
*/
|
||||||
public static long getTimeout(String token) {
|
public static long getTimeout(String token) {
|
||||||
return SaManager.getSaTemp().getTimeout(token);
|
return SaManager.getSaTemp().getTimeout(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除一个 token
|
* 获取指定服务指定 Token 的剩余有效期,单位:秒
|
||||||
* @param token 指定token
|
* <p> 返回值 -1 代表永久,-2 代表token无效
|
||||||
|
* @param service 服务标识
|
||||||
|
* @param token 指定 Token
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static long getTimeout(String service, String token) {
|
||||||
|
return SaManager.getSaTemp().getTimeout(service, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除一个 Token
|
||||||
|
* @param token 指定 Token
|
||||||
*/
|
*/
|
||||||
public static void deleteToken(String token) {
|
public static void deleteToken(String token) {
|
||||||
SaManager.getSaTemp().deleteToken(token);
|
SaManager.getSaTemp().deleteToken(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除一个 Token
|
||||||
|
* @param service 服务标识
|
||||||
|
* @param token 指定 Token
|
||||||
|
*/
|
||||||
|
public static void deleteToken(String service, String token) {
|
||||||
|
SaManager.getSaTemp().deleteToken(service, token);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,6 +103,16 @@ public class SaFoxUtil {
|
|||||||
public static boolean equals(Object a, Object b) {
|
public static boolean equals(Object a, Object b) {
|
||||||
return (a == b) || (a != null && a.equals(b));
|
return (a == b) || (a != null && a.equals(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 比较两个对象是否不相等
|
||||||
|
* @param a 第一个对象
|
||||||
|
* @param b 第二个对象
|
||||||
|
* @return 两个对象是否不相等
|
||||||
|
*/
|
||||||
|
public static boolean notEquals(Object a, Object b) {
|
||||||
|
return !equals(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 以当前时间戳和随机int数字拼接一个随机字符串
|
* 以当前时间戳和随机int数字拼接一个随机字符串
|
||||||
|
|||||||
@@ -95,6 +95,11 @@ public class SaTokenConsts {
|
|||||||
*/
|
*/
|
||||||
public static final String DEFAULT_SAFE_AUTH_SERVICE = "important";
|
public static final String DEFAULT_SAFE_AUTH_SERVICE = "important";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 常量key标记: 临时 Token 认证模块,默认的业务类型
|
||||||
|
*/
|
||||||
|
public static final String DEFAULT_TEMP_TOKEN_SERVICE = "record";
|
||||||
|
|
||||||
|
|
||||||
// =================== token-style 相关 ===================
|
// =================== token-style 相关 ===================
|
||||||
|
|
||||||
|
|||||||
@@ -104,6 +104,9 @@ SaToken 中的所有异常都是继承于 `SaTokenException` 的,也就是说
|
|||||||
| 12117 | RSA 私钥加密异常 |
|
| 12117 | RSA 私钥加密异常 |
|
||||||
| 12118 | RSA 公钥解密异常 |
|
| 12118 | RSA 公钥解密异常 |
|
||||||
| 12119 | RSA 私钥解密异常 |
|
| 12119 | RSA 私钥解密异常 |
|
||||||
|
| 12201 | 参与参数签名的秘钥不可为空 |
|
||||||
|
| 12202 | 给定的签名无效 |
|
||||||
|
| 12203 | timestamp 超出允许的范围 |
|
||||||
|
|
||||||
|
|
||||||
#### sa-token-servlet
|
#### sa-token-servlet
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ import io.jsonwebtoken.SignatureAlgorithm;
|
|||||||
public class SaJwtUtil {
|
public class SaJwtUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* key: value
|
* key: value 前缀
|
||||||
*/
|
*/
|
||||||
public static final String KEY_VALUE = "value";
|
public static final String KEY_VALUE = "value_";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* key: 有效期 (时间戳)
|
* key: 有效期 (时间戳)
|
||||||
@@ -30,12 +30,13 @@ public class SaJwtUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据指定值创建 jwt-token
|
* 根据指定值创建 jwt-token
|
||||||
|
* @param key 存储value使用的key
|
||||||
* @param value 要保存的值
|
* @param value 要保存的值
|
||||||
* @param timeout token有效期 (单位 秒)
|
* @param timeout token有效期 (单位 秒)
|
||||||
* @param keyt 秘钥
|
* @param keyt 秘钥
|
||||||
* @return jwt-token
|
* @return jwt-token
|
||||||
*/
|
*/
|
||||||
public static String createToken(Object value, long timeout, String keyt) {
|
public static String createToken(String key, Object value, long timeout, String keyt) {
|
||||||
// 计算eff有效期
|
// 计算eff有效期
|
||||||
long eff = timeout;
|
long eff = timeout;
|
||||||
if(timeout != NEVER_EXPIRE) {
|
if(timeout != NEVER_EXPIRE) {
|
||||||
@@ -44,7 +45,7 @@ public class SaJwtUtil {
|
|||||||
// 在这里你可以使用官方提供的claim方法构建载荷,也可以使用setPayload自定义载荷,但是两者不可一起使用
|
// 在这里你可以使用官方提供的claim方法构建载荷,也可以使用setPayload自定义载荷,但是两者不可一起使用
|
||||||
JwtBuilder builder = Jwts.builder()
|
JwtBuilder builder = Jwts.builder()
|
||||||
// .setHeaderParam("typ", "JWT")
|
// .setHeaderParam("typ", "JWT")
|
||||||
.claim(KEY_VALUE, value)
|
.claim(KEY_VALUE + key, value)
|
||||||
.claim(KEY_EFF, eff)
|
.claim(KEY_EFF, eff)
|
||||||
.signWith(SignatureAlgorithm.HS256, keyt.getBytes());
|
.signWith(SignatureAlgorithm.HS256, keyt.getBytes());
|
||||||
// 生成jwt-token
|
// 生成jwt-token
|
||||||
@@ -68,11 +69,12 @@ public class SaJwtUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 从一个 jwt-token 解析出载荷, 并取出数据
|
* 从一个 jwt-token 解析出载荷, 并取出数据
|
||||||
|
* @param key 存储value使用的key
|
||||||
* @param jwtToken JwtToken值
|
* @param jwtToken JwtToken值
|
||||||
* @param keyt 秘钥
|
* @param keyt 秘钥
|
||||||
* @return 值
|
* @return 值
|
||||||
*/
|
*/
|
||||||
public static Object getValue(String jwtToken, String keyt) {
|
public static Object getValue(String key, String jwtToken, String keyt) {
|
||||||
// 取出数据
|
// 取出数据
|
||||||
Claims claims = parseToken(jwtToken, keyt);
|
Claims claims = parseToken(jwtToken, keyt);
|
||||||
|
|
||||||
@@ -83,7 +85,7 @@ public class SaJwtUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取数据
|
// 获取数据
|
||||||
return claims.get(KEY_VALUE);
|
return claims.get(KEY_VALUE + key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,10 +94,15 @@ public class SaJwtUtil {
|
|||||||
* @param keyt 秘钥
|
* @param keyt 秘钥
|
||||||
* @return 值
|
* @return 值
|
||||||
*/
|
*/
|
||||||
public static long getTimeout(String jwtToken, String keyt) {
|
public static long getTimeout(String key, String jwtToken, String keyt) {
|
||||||
// 取出数据
|
// 取出数据
|
||||||
Claims claims = parseToken(jwtToken, keyt);
|
Claims claims = parseToken(jwtToken, keyt);
|
||||||
|
|
||||||
|
// 如果给定的key不对
|
||||||
|
if(claims.get(KEY_VALUE + key) == null) {
|
||||||
|
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||||
|
}
|
||||||
|
|
||||||
// 验证是否超时
|
// 验证是否超时
|
||||||
Long eff = claims.get(KEY_EFF, Long.class);
|
Long eff = claims.get(KEY_EFF, Long.class);
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ public class SaTempForJwt implements SaTempInterface {
|
|||||||
* 根据value创建一个token
|
* 根据value创建一个token
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String createToken(Object value, long timeout) {
|
public String createToken(String service, Object value, long timeout) {
|
||||||
String token = SaJwtUtil.createToken(value, timeout, getJwtSecretKey());
|
String token = SaJwtUtil.createToken(service, value, timeout, getJwtSecretKey());
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,8 +27,8 @@ public class SaTempForJwt implements SaTempInterface {
|
|||||||
* 解析token获取value
|
* 解析token获取value
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Object parseToken(String token) {
|
public Object parseToken(String service, String token) {
|
||||||
Object value = SaJwtUtil.getValue(token, getJwtSecretKey());
|
Object value = SaJwtUtil.getValue(service, token, getJwtSecretKey());
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,8 +36,8 @@ public class SaTempForJwt implements SaTempInterface {
|
|||||||
* 返回指定token的剩余有效期,单位:秒
|
* 返回指定token的剩余有效期,单位:秒
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public long getTimeout(String token) {
|
public long getTimeout(String service, String token) {
|
||||||
long timeout = SaJwtUtil.getTimeout(token, getJwtSecretKey());
|
long timeout = SaJwtUtil.getTimeout(service, token, getJwtSecretKey());
|
||||||
return timeout;
|
return timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ public class SaTempForJwt implements SaTempInterface {
|
|||||||
* 删除一个token
|
* 删除一个token
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void deleteToken(String token) {
|
public void deleteToken(String service, String token) {
|
||||||
throw new ApiDisabledException("jwt cannot delete token").setCode(SaTempJwtErrorCode.CODE_30302);
|
throw new ApiDisabledException("jwt cannot delete token").setCode(SaTempJwtErrorCode.CODE_30302);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ public class SaJsonTemplateForJackson implements SaJsonTemplate {
|
|||||||
* @param obj 对象
|
* @param obj 对象
|
||||||
* @return 转换后的 json 字符串
|
* @return 转换后的 json 字符串
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String toJsonString(Object obj) {
|
public String toJsonString(Object obj) {
|
||||||
try {
|
try {
|
||||||
return objectMapper.writeValueAsString(obj);
|
return objectMapper.writeValueAsString(obj);
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ public class SaSignTemplateTest {
|
|||||||
|
|
||||||
// 连接参数列表
|
// 连接参数列表
|
||||||
@Test
|
@Test
|
||||||
public void testJoinParams() {
|
public void testJoinParamsDictSort() {
|
||||||
SoMap map = SoMap.getSoMap()
|
SoMap map = SoMap.getSoMap()
|
||||||
.set("name", "zhang")
|
.set("name", "zhang")
|
||||||
.set("age", 18)
|
.set("age", 18)
|
||||||
.set("sex", "女");
|
.set("sex", "女");
|
||||||
String str = SaManager.getSaSignTemplate().joinParams(map);
|
String str = SaManager.getSaSignTemplate().joinParamsDictSort(map);
|
||||||
|
|
||||||
// 按照音序排列
|
// 按照音序排列
|
||||||
Assertions.assertEquals(str, "age=18&name=zhang&sex=女");
|
Assertions.assertEquals(str, "age=18&name=zhang&sex=女");
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
import cn.dev33.satoken.SaManager;
|
import cn.dev33.satoken.SaManager;
|
||||||
import cn.dev33.satoken.dao.SaTokenDao;
|
import cn.dev33.satoken.dao.SaTokenDao;
|
||||||
import cn.dev33.satoken.temp.SaTempUtil;
|
import cn.dev33.satoken.temp.SaTempUtil;
|
||||||
|
import cn.dev33.satoken.util.SaTokenConsts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 临时Token模块测试
|
* 临时Token模块测试
|
||||||
@@ -23,15 +24,21 @@ public class SaTempTest {
|
|||||||
// 生成token
|
// 生成token
|
||||||
String token = SaTempUtil.createToken("group-1014", 200);
|
String token = SaTempUtil.createToken("group-1014", 200);
|
||||||
Assertions.assertNotNull(token);
|
Assertions.assertNotNull(token);
|
||||||
|
// System.out.println(((SaTokenDaoDefaultImpl)SaManager.getSaTokenDao()).dataMap);
|
||||||
|
|
||||||
// 解析token
|
// 解析token
|
||||||
String value = SaTempUtil.parseToken(token, String.class);
|
String value = SaTempUtil.parseToken(token, String.class);
|
||||||
Assertions.assertEquals(value, "group-1014");
|
Assertions.assertEquals(value, "group-1014");
|
||||||
Assertions.assertEquals(dao.getObject("satoken:temp-token:" + token), "group-1014");
|
Assertions.assertEquals(dao.getObject("satoken:temp-token:" + SaTokenConsts.DEFAULT_TEMP_TOKEN_SERVICE + ":" + token), "group-1014");
|
||||||
|
|
||||||
// 默认类型
|
// 默认类型
|
||||||
Object value3 = SaTempUtil.parseToken(token);
|
Object value3 = SaTempUtil.parseToken(token);
|
||||||
Assertions.assertEquals(value3, "group-1014");
|
Assertions.assertEquals(value3, "group-1014");
|
||||||
|
|
||||||
|
// 转换类型
|
||||||
|
String value4 = SaTempUtil.parseToken(token, String.class);
|
||||||
|
Assertions.assertEquals(value4, "group-1014");
|
||||||
|
|
||||||
// 过期时间
|
// 过期时间
|
||||||
long timeout = SaTempUtil.getTimeout(token);
|
long timeout = SaTempUtil.getTimeout(token);
|
||||||
Assertions.assertTrue(timeout > 195);
|
Assertions.assertTrue(timeout > 195);
|
||||||
@@ -40,7 +47,45 @@ public class SaTempTest {
|
|||||||
SaTempUtil.deleteToken(token);
|
SaTempUtil.deleteToken(token);
|
||||||
String value2 = SaTempUtil.parseToken(token, String.class);
|
String value2 = SaTempUtil.parseToken(token, String.class);
|
||||||
Assertions.assertEquals(value2, null);
|
Assertions.assertEquals(value2, null);
|
||||||
Assertions.assertEquals(dao.getObject("satoken:temp-token:" + token), null);
|
Assertions.assertEquals(dao.getObject("satoken:temp-token:" + SaTokenConsts.DEFAULT_TEMP_TOKEN_SERVICE + ":" + token), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试:临时Token认证模块,带 Service 参数
|
||||||
|
@Test
|
||||||
|
public void testSaTempService() {
|
||||||
|
SaTokenDao dao = SaManager.getSaTokenDao();
|
||||||
|
|
||||||
|
// 生成token
|
||||||
|
String token = SaTempUtil.createToken("shop", "1001", 200);
|
||||||
|
Assertions.assertNotNull(token);
|
||||||
|
// System.out.println(((SaTokenDaoDefaultImpl)SaManager.getSaTokenDao()).dataMap);
|
||||||
|
|
||||||
|
// 解析token
|
||||||
|
String value = SaTempUtil.parseToken("shop", token, String.class);
|
||||||
|
Assertions.assertEquals(value, "1001");
|
||||||
|
Assertions.assertEquals(dao.getObject("satoken:temp-token:" + "shop" + ":" + token), "1001");
|
||||||
|
|
||||||
|
// 默认类型
|
||||||
|
Object value3 = SaTempUtil.parseToken("shop", token);
|
||||||
|
Assertions.assertEquals(value3, "1001");
|
||||||
|
|
||||||
|
// 转换类型
|
||||||
|
String value4 = SaTempUtil.parseToken("shop", token, String.class);
|
||||||
|
Assertions.assertEquals(value4, "1001");
|
||||||
|
|
||||||
|
// service 参数不对的情况下,无法取出
|
||||||
|
String value5 = SaTempUtil.parseToken("goods", token, String.class);
|
||||||
|
Assertions.assertNull(value5);
|
||||||
|
|
||||||
|
// 过期时间
|
||||||
|
long timeout = SaTempUtil.getTimeout("shop", token);
|
||||||
|
Assertions.assertTrue(timeout > 195);
|
||||||
|
|
||||||
|
// 回收token
|
||||||
|
SaTempUtil.deleteToken("shop", token);
|
||||||
|
String value2 = SaTempUtil.parseToken("shop", token, String.class);
|
||||||
|
Assertions.assertEquals(value2, null);
|
||||||
|
Assertions.assertEquals(dao.getObject("satoken:temp-token:" + "shop" + ":" + token), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user