三方接口加签、验签方案

1,392 阅读3分钟

平台三方接口加签、验签方案

一、需求背景

平台为三方提供服务时,常常需要对接口请求做身份鉴权,并防止请求伪造,请求重放,参数篡改等恶意行为的发生,因此需要提供一套接口加签与验签的流程。

二、问题与方案

由于需求背景不涉及业务数据的加密隐藏,故不使用对业务数据进行非对称加密(RSA)的处理方式,业务参数不参与签名。同时,为了减少三方对接的复杂度,也不采用 OAuth2 的方式做双 Token 鉴权。但验签方案仍需解决下面三个问题。

防止请求伪造问题

平台给三方线下发放成对的 AppKey 与 AppSecret,AppSecret 参与本地签名 Signature 生成。三方调用接口时携带参数 AppKey 与 Signature,平台做验签操作,确认是来自平台注册渠道的真实请求。

解决请求重放问题

上面解决了三方调用的身份鉴权问题,但仍会发生重复使用请求参数伪造二次请求的可能。可以为每一个请求生成一个随机字符串 Nonce 作为唯一流水号(可使用UUID方案)参与签名流程。通过记录所有 Nonce,校验 Nonce 重复达到防止多次请求的目的。

但持久化 Nonce 的存储与查询成本过高,而每个请求其实都有一定的时效性,所以可以使用 Timestamp + Nonce 的方案进行优化。

首先假设请求的时效性在当前服务器时间前后 x 分钟以内,要求三方请求在参数中增加时间戳 Timestamp,并且 Timestamp 参与签名计算,防止请求时间被随意篡改。平台接收到请求后,获取其中的 Timestamp,一旦超出服务器时间前后 x 分钟范围,则直接过滤请求并返回请求已过期。

如果请求在时间范围以内,再通过校验 Nonce 重复,以拦截接口二次调用。此方案平台服务器只需要记录最近 x 分钟以内的请求 Nonce 即可,记录方法可以使用 Redis 实现。

解决参数篡改问题

由于使用了 Nonce 方案给单位时间内的请求增加了唯一标识,接口无法二次调用,所以不存在根据已知的请求去篡改参数绕过验签的问题。

三、具体实现步骤

sequenceDiagram
三方->>平台: 注册合作渠道
平台->>三方: 发放 AppKey 与 AppSecret
三方->>三方: ① 生成签名 Signature = SHA1(AppSecret + Nonce + Timestamp)
三方->>平台: ② 发起请求,携带参数:AppKey,Nonce,Timestamp,Signature
平台->>平台: ③ 校验 Timestamp
平台-->>三方: Timestamp 超出时间范围,返回过期请求
平台->>平台: ④ 校验 Nonce
平台-->>三方: Nonce 存在重复,返回重复请求
平台->>平台: ⑤ 校验 Signature
平台-->>三方: Signature 不一致,返回参数错误
平台->>三方: ⑥ 返回请求校验成功
  1. 接口调用方使用平台方分配的 AppSecret,随机字符串 Nonce(最大长度128个字符),时间戳 Timestamp(秒),三个参数按顺序拼接后做 SHA1 哈希计算,生成十六进制字符串作为校验签名 Signature。
  2. 接口调用方在 Header 中携带 AppKey,Nonce,Timestamp,Signature 四个参数发起请求。
  3. 平台方接收请求获得参数后,首先校验 Timestamp 是否在当前服务器时间前后 5 分钟范围内,不在范围内直接过滤请求,返回过期请求。
  4. 校验最近 5 分钟内是否有包含同样 Nonce 信息的请求,如果有则直接过滤,返回重复请求。
  5. 通过 AppKey 查询对应的 AppSecret,同样通过 SHA1(AppSecret + Nonce + Timestamp) 的方式计算得到签名 ServiceSignature,判断 Signature 与 ServiceSignature 是否一致,如果不一致则过滤请求,返回参数错误。
  6. 通过所有校验,返回请求校验成功。