Secret 签名算法技术规范

一、算法目的

为防止接口恶意调用,所有请求需携带动态生成的secret参数。本规范详细说明secret的计算规则,服务端将通过相同算法验证请求合法性,拒绝无效签名。

二、算法流程图

[参数预处理][URL编码][ASCII排序][字符串拼接][Token追加][MD5哈希]

三、计算步骤说明

步骤1:参数预处理

1.过滤空值参数

移除参数名或参数值为空的字段(空字符串、null值等)

2.排除secret字段

需显式去除请求参数中的secret字段本身
预处理规则示例:

原始参数: {account: "40015752421", "corpId": "82734fee", secret: "B45A5E8F7DC1456BA4FC05FFEC351FA3", data="", reply=null "templateId": "220427091304079"}
处理后参数: {account: "40015752421", "corpId": "82734fee", "templateId": "220427091304079"}

步骤2:URL编码处理

  • 所有参数名参数值进行application/x-www-form-urlencoded编码

  • 编码字符集:UTF-8

  • 注意保留已编码字符(如原参数值中的%20不做二次编码)

编码规则示例:

原始参数: data=["小明","小李"],mobile=13788888888,18699999999
编码结果: data=%5B%22%E5%B0%8F%E6%98%8E%22%2C%22%E5%B0%8F%E6%9D%8E%22%5D,mobile=13788888888%2C18699999999

步骤3:ASCII排序拼接

1.按参数名ASCII码升序排列

示例:account(97) < appver(97) < corpId(99) < data(100)

2.键值拼接规则

按排序后的顺序拼接为参数名1参数值1参数名2参数值2…格式

拼接示例:

排序后参数顺序: account, appver, corpId, data...
拼接结果: "account40015752421appver1corpId82734fee..." 

步骤4:Token追加

  • 在拼接字符串末尾直接追加系统分配的token

  • 注意:token不做任何编码处理

追加示例:

拼接字符串 += "3551a828-ca81-40b5-af5d-54f39074a7d4"

步骤5:生成MD5签名

  • 对最终字符串进行标准MD5哈希计算

  • 输出要求:32位大写十六进制字符串

哈希示例:

输入字符串: "account40015752421...token"
MD5结果: "8DBA355E3830E234936F357834DA22E8"

四、完整示例演算

初始参数

{
  "account": "40015752421",
  "appver": "1",
  "corpId": "82734fee-e05d-40df-b442-f29879c8b8a8",
  "data": ["小明","小李"],
  "mobile": "13788888888,18699999999",
  "reply": 0,
  "replyurl": null,
  "secret": "B45A5E8F7DC1456BA4FC05FFEC351FA3",
  "tag": "",
  "templateId": "220427091304079",
  "timestamp": "20250126111500",
  "user": "40015752421_dev"
}

演算过程

1.预处理后参数

account=40015752421&appver=1&corpId=82734fee-e05d-40df-b442-f29879c8b8a8&data=["小明","小李"]&mobile=13788888888,18699999999&reply=0&templateId=220427091304079&timestamp=20250126111500&user=40015752421_dev

2.URL编码结果

account=40015752421
appver=1
corpId=82734fee-e05d-40df-b442-f29879c8b8a8
data=%5B%22%E5%B0%8F%E6%98%8E%22%2C%22%E5%B0%8F%E6%9D%8E%22%5D
mobile=13788888888%2C18699999999
reply=0
templateId=220427091304079
timestamp=20250126111500
user=40015752421_dev

3.排序拼接结果

"account40015752421appver1corpId82734fee-e05d-40df-b442-f29879c8b8a8data%5B%22%E5%B0%8F%E6%98%8E%22%2C%22%E5%B0%8F%E6%9D%8E%22%5Dmobile13788888888%2C18699999999reply0templateId220427091304079timestamp20250126111500user40015752421_dev"

4.最终哈希输入

"account40015752421appver1corpId82734fee-e05d-40df-b442-f29879c8b8a8data%5B%22%E5%B0%8F%E6%98%8E%22%2C%22%E5%B0%8F%E6%9D%8E%22%5Dmobile13788888888%2C18699999999reply0templateId220427091304079timestamp20250126111500user40015752421_dev3551a828-ca81-40b5-af5d-54f39074a7d4"

5.生成Secret

可通过一下方式验证:

import hashlib
s = "account40015752421appver1corpId82734fee-e05d-40df-b442-f29879c8b8a8data%5B%22%E5%B0%8F%E6%98%8E%22%2C%22%E5%B0%8F%E6%9D%8E%22%5Dmobile13788888888%2C18699999999reply0templateId220427091304079timestamp20250126111500user40015752421_dev3551a828-ca81-40b5-af5d-54f39074a7d4"
print(hashlib.md5(s.encode()).hexdigest().upper())

最终计算结果:

8DBA355E3830E234936F357834DA22E8

五、注意事项

1.编码一致性

确保URL编码实现符合RFC 3986标准,Python推荐使用urllib.parse.quote,Java推荐使用URLEncoder.encode

重点关注一下编码差异:

原始字符    URL编码后
[            %5B
"            %22
,            %2C
中文        %E5%B0%8F%...

边界案例测试

空数组参数:data=[] → data%5B%5D

纯数字参数:mobile=1380013800 → 无需编码

布尔值参数:reply=true → replytrue

2.排序稳定性

当参数名相同时(理论上不应存在),需保持参数原始顺序

3.空值处理

参数值为0false等有效值需保留,仅过滤真正空值参数

4.测试验证

建议使用官方提供的在线验证工具进行算法正确性校验

5.安全建议

token需严格保密,建议定期轮换,禁止在客户端硬编码

文档更新时间: 2025-02-20 16:55   作者:admin