feat: API 参数签名配置支持自定义摘要算法

This commit is contained in:
click33
2025-03-09 19:44:45 +08:00
parent abc2b0be69
commit 1c4af4cc03
4 changed files with 103 additions and 30 deletions
@@ -15,6 +15,10 @@
*/ */
package cn.dev33.satoken.config; package cn.dev33.satoken.config;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.fun.SaParamRetFunction;
import cn.dev33.satoken.secure.SaSecureUtil;
/** /**
* Sa-Token API 接口签名/验签 相关配置类 * Sa-Token API 接口签名/验签 相关配置类
* *
@@ -36,6 +40,10 @@ public class SaSignConfig {
*/ */
private long timestampDisparity = 1000 * 60 * 15; private long timestampDisparity = 1000 * 60 * 15;
/**
* 对 fullStr 的摘要算法
*/
private String digestAlgo = "md5";
public SaSignConfig() { public SaSignConfig() {
} }
@@ -48,6 +56,70 @@ public class SaSignConfig {
this.secretKey = secretKey; this.secretKey = secretKey;
} }
// -------------- 扩展方法
/**
* 计算保存 nonce 时应该使用的 ttl,单位:秒
* @return /
*/
public long getSaveNonceExpire() {
// 如果 timestampDisparity >= 0,则 nonceTtl 的值等于 timestampDisparity 的值,单位转秒
if(timestampDisparity >= 0) {
return timestampDisparity / 1000;
}
// 否则,nonceTtl 的值为 24 小时
else {
return 60 * 60 * 24;
}
}
// -------------- 策略函数
/**
* 对 fullStr 的摘要算法函数
*/
public SaParamRetFunction<String, String> digestMethod = (fullStr) -> {
// md5
if(digestAlgo.equalsIgnoreCase("md5")) {
return SaSecureUtil.md5(fullStr);
}
// sha1
if(digestAlgo.equalsIgnoreCase("sha1")) {
return SaSecureUtil.sha1(fullStr);
}
// sha256
if(digestAlgo.equalsIgnoreCase("sha256")) {
return SaSecureUtil.sha256(fullStr);
}
// sha384
if(digestAlgo.equalsIgnoreCase("sha384")) {
return SaSecureUtil.sha384(fullStr);
}
// sha512
if(digestAlgo.equalsIgnoreCase("sha512")) {
return SaSecureUtil.sha512(fullStr);
}
// 未知
throw new SaTokenException("不支持的摘要算法:" + digestAlgo + ",你可以自定义摘要算法函数实现");
};
/**
* 设置: 对 fullStr 的摘要算法函数
*
* @param digestMethod /
* @return 对象自身
*/
public SaSignConfig setDigestMethod(SaParamRetFunction<String, String> digestMethod) {
this.digestMethod = digestMethod;
return this;
}
// -------------- get/set
/** /**
* 获取 API 调用签名秘钥 * 获取 API 调用签名秘钥
* *
@@ -95,18 +167,22 @@ public class SaSignConfig {
} }
/** /**
* 计算保存 nonce 时应该使用的 ttl,单位:秒 * 获取 对 fullStr 的摘要算法
*
* @return digestAlgo 对 fullStr 的摘要算法
*/
public String getDigestAlgo() {
return this.digestAlgo;
}
/**
* 设置 对 fullStr 的摘要算法
* @param digestAlgo /
* @return / * @return /
*/ */
public long getSaveNonceExpire() { public SaSignConfig setDigestAlgo(String digestAlgo) {
// 如果 timestampDisparity >= 0,则 nonceTtl 的值等于 timestampDisparity 的值,单位转秒 this.digestAlgo = digestAlgo;
if(timestampDisparity >= 0) { return this;
return timestampDisparity / 1000;
}
// 否则,nonceTtl 的值为 24 小时
else {
return 60 * 60 * 24;
}
} }
@Override @Override
@@ -117,15 +193,4 @@ public class SaSignConfig {
+ "]"; + "]";
} }
/**
* 设置:是否校验 nonce 随机字符串
* <h2> isCheckNonce 方案已废弃,不再提供此配置项 </h2>
*
* @param isCheckNonce /
*/
@Deprecated
public void setIsCheckNonce(Boolean isCheckNonce) {
System.err.println("--------- isCheckNonce 方案已废弃,不再提供此配置项 ---------");
}
} }
@@ -20,7 +20,6 @@ import cn.dev33.satoken.config.SaSignConfig;
import cn.dev33.satoken.context.model.SaRequest; import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.error.SaErrorCode; import cn.dev33.satoken.error.SaErrorCode;
import cn.dev33.satoken.exception.SaSignException; import cn.dev33.satoken.exception.SaSignException;
import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.util.SaFoxUtil; import cn.dev33.satoken.util.SaFoxUtil;
import java.util.Map; import java.util.Map;
@@ -173,7 +172,7 @@ public class SaSignTemplate {
// 计算签名 // 计算签名
String paramsStr = joinParamsDictSort(paramsMap); String paramsStr = joinParamsDictSort(paramsMap);
String fullStr = paramsStr + "&" + key + "=" + secretKey; String fullStr = paramsStr + "&" + key + "=" + secretKey;
String signStr = abstractStr(fullStr); String signStr = digestFullStr(fullStr);
// 输入日志,方便调试 // 输入日志,方便调试
log.debug("fullStr:{}", fullStr); log.debug("fullStr:{}", fullStr);
@@ -188,8 +187,8 @@ public class SaSignTemplate {
* @param fullStr 待摘要的字符串 * @param fullStr 待摘要的字符串
* @return 签名 * @return 签名
*/ */
public String abstractStr(String fullStr) { public String digestFullStr(String fullStr) {
return SaSecureUtil.md5(fullStr); return getSignConfigOrGlobal().digestMethod.run(fullStr);
} }
/** /**
@@ -281,7 +280,7 @@ public class SaSignTemplate {
} }
/** /**
* 判断:给定的参数 + 秘钥 生成的签名是否为有效签名 * 判断:给定的参数 生成的签名是否为有效签名
* @param paramsMap 参数列表 * @param paramsMap 参数列表
* @param sign 待验证的签名 * @param sign 待验证的签名
* @return 签名是否有效 * @return 签名是否有效
@@ -292,7 +291,7 @@ public class SaSignTemplate {
} }
/** /**
* 校验:给定的参数 + 秘钥 生成的签名是否为有效签名,如果签名无效则抛出异常 * 校验:给定的参数 生成的签名是否为有效签名,如果签名无效则抛出异常
* @param paramsMap 参数列表 * @param paramsMap 参数列表
* @param sign 待验证的签名 * @param sign 待验证的签名
*/ */
@@ -349,6 +348,9 @@ public class SaSignTemplate {
// 通过 √ // 通过 √
} }
// ----------- Web 请求相关 封装
/** /**
* 判断:一个请求中的 nonce、timestamp、sign 是否均为合法的 * 判断:一个请求中的 nonce、timestamp、sign 是否均为合法的
* @param request 待校验的请求对象 * @param request 待校验的请求对象
@@ -382,7 +384,7 @@ public class SaSignTemplate {
* @param paramNames 指定的参数名称,不可为空,如果传入空数组则代表只拿 timestamp、nonce、sign 三个参数 * @param paramNames 指定的参数名称,不可为空,如果传入空数组则代表只拿 timestamp、nonce、sign 三个参数
* @return 提取出的参数 * @return 提取出的参数
*/ */
public Map<String, String> takeRequestParam(SaRequest request, String [] paramNames) { protected Map<String, String> takeRequestParam(SaRequest request, String [] paramNames) {
Map<String, String> paramMap = new TreeMap<>(); Map<String, String> paramMap = new TreeMap<>();
// 此三个参数是必须获取的 // 此三个参数是必须获取的
@@ -119,7 +119,7 @@ public class SaSignUtil {
} }
/** /**
* 判断:给定的参数 + 秘钥 生成的签名是否为有效签名 * 判断:给定的参数 生成的签名是否为有效签名
* @param paramsMap 参数列表 * @param paramsMap 参数列表
* @param sign 待验证的签名 * @param sign 待验证的签名
* @return 签名是否有效 * @return 签名是否有效
@@ -129,7 +129,7 @@ public class SaSignUtil {
} }
/** /**
* 校验:给定的参数 + 秘钥 生成的签名是否为有效签名,如果签名无效则抛出异常 * 校验:给定的参数 生成的签名是否为有效签名,如果签名无效则抛出异常
* @param paramsMap 参数列表 * @param paramsMap 参数列表
* @param sign 待验证的签名 * @param sign 待验证的签名
*/ */
@@ -154,6 +154,9 @@ public class SaSignUtil {
SaManager.getSaSignTemplate().checkParamMap(paramMap); SaManager.getSaSignTemplate().checkParamMap(paramMap);
} }
// ----------- Web 请求相关 封装
/** /**
* 判断:一个请求中的 nonce、timestamp、sign 是否均为合法的 * 判断:一个请求中的 nonce、timestamp、sign 是否均为合法的
* @param request 待校验的请求对象 * @param request 待校验的请求对象
@@ -18,6 +18,9 @@ sa-token:
token-style: uuid token-style: uuid
# 是否输出操作日志 # 是否输出操作日志
is-log: true is-log: true
sign:
# token签名密钥
secret-key: abc123
spring: spring:
# redis配置 # redis配置