一、需求背景
在为第三方提供服务时,平台需要确保接口请求的安全性,防止恶意行为如身份伪造、请求重放和参数篡改。为此,设计一套有效的接口加签与验签流程至关重要。本方案旨在通过简洁且高效的方式实现这一目标,同时尽量减少对接的复杂度。
二、问题与解决方案
1. 防止请求伪造问题
问题描述:确保请求来自已注册的合法第三方应用,防止未授权的应用冒充合法应用发起请求。
解决方案:
-
AppKey 和 AppSecret 分发:平台为每个第三方应用分配一对唯一的
AppKey
和AppSecret
。其中,AppSecret
是一个密钥,用于生成签名(Signature)。 -
签名生成:第三方在调用接口时,使用
AppSecret
对请求参数进行签名,并将生成的Signature
作为参数传递给平台。 -
签名验证:平台接收到请求后,使用存储的
AppSecret
重新计算签名,并与请求中携带的Signature
进行比对。如果两者一致,则认为请求是合法的;否则,拒绝该请求。
2. 解决请求重放问题
问题描述:防止恶意用户通过重复发送相同的请求来绕过系统限制或造成其他安全风险。
解决方案:
-
Nonce 机制:为每个请求生成一个随机字符串
Nonce
,作为唯一标识符。Nonce
参与签名计算,并在每次请求时都不同。 -
时间戳校验:引入时间戳
Timestamp
参数,要求第三方在请求中包含当前的时间戳,并将其参与签名计算。平台接收请求后,检查时间戳是否在允许的时间范围内(例如,前后 x 分钟内),以确保请求的新鲜度。 -
Nonce 存储与校验:平台使用 Redis 等高性能缓存系统记录最近 x 分钟内的所有
Nonce
值。当接收到新的请求时,首先检查Nonce
是否已经存在于缓存中。如果存在,则拒绝该请求;否则,将其添加到缓存中并继续处理。
3.签名算法与验签过程
1. 签名算法
签名算法用于生成请求的签名,确保请求的完整性和来源的合法性。以下是详细的签名计算步骤和注意事项。
计算步骤
-
参数排序:
-
将所有需要参与签名的
<key, value>
请求参数对按key
进行字典升序排序,得到有序的参数对列表N
。 -
示例:假设请求参数为
{ "param2": "value2", "param1": "value1", "param3": "value3" }
,排序后的列表N
为[("param1", "value1"), ("param2", "value2"), ("param3", "value3")]
。
-
-
拼接字符串:
-
将排序后的参数对列表
N
按 URL 键值对的格式拼接成一个字符串T
。每个键值对之间用&
分隔,且value
部分需要进行 URL 编码(使用大写字母)。 -
示例:假设排序后的参数对列表
N
为[("param1", "value1"), ("param2", "value2"), ("param3", "value3")]
,拼接后的字符串T
为param1=value1¶m2=value2¶m3=value3
。
-
-
添加应用密钥:
-
将应用密钥以
app_key
为键名,组成一个新的 URL 键值对,并将其拼接到字符串T
的末尾,得到最终的字符串S
。 -
示例:假设应用密钥为
my_secret_key
,则最终的字符串S
为param1=value1¶m2=value2¶m3=value3&app_key=my_secret_key
。
-
-
MD5 运算:
-
对字符串
S
进行 MD5 运算,将得到的 MD5 值转换为大写形式&#x
-