接口签名规范

签名目的

防止请求篡改与重放。服务端基于约定的请求要素与双方共享的 appSecret 计算签名,通过校验签名一致性、timestamp 时间窗及 nonce 去重机制,保障请求的安全性。

签名要素(参与签名的数据)

需对以下三类数据按约定规则规范化后拼接,作为签名计算的基础:

  1. URL 的查询参数(query string)
  2. 需要签名的请求头(自定义头部),例如:appId、nonce、timestamp
  3. 请求体(raw body 字符串),通常为 JSON 原始字符串(空体则视为空字符串)

注:编码/解码方式必须与后端一致。本文示例规则为:对 query 和 header 的键值先进行 URL 解码,再按键名称字典序排序并使用 key=value 串联。

规范化与拼接规则(详细步骤)

1. Query 参数处理

  • 从请求 URL 中提取 ? 之后的 queryString;若无 query,则视为空字符串。
  • 按 key 升序(字典序)排序,以 k=v 形式拼接,不同参数间用 & 连接,得到 sortedQueryString
    示例:a=1&b=2

2. Header 处理

  • 提取约定的参与签名的 header 列表(示例:['appId','nonce','timestamp']),header 名称大小写以约定为准(示例使用小驼峰)。
  • 对每个存在的 header 值取原始字符串(不额外 encode),不存在的 header 直接跳过。
  • 按 key 升序排序,以 k=v 形式拼接,不同 header 间用 & 连接,得到 sortedHeaderString

3. Body 处理

  • Content-Typeapplication/json 且 body 有内容,取 body 的原始 raw 字符串(不修改空格/缩进,与服务端序列化方式一致)。
  • 若无 body,视为空字符串 ''

4. 最终拼接

示例约定
signatureBaseString = sortedQueryString + '&' + sortedHeaderString + '&' + requestBodyString

说明:即使某一部分为空,仍保留 & 作为分隔(需与后端达成一致,本文示例采用固定三段拼接并保留分隔符)。

签名算法

  1. 使用 HMAC-SHA256(或后端指定算法),以 appSecret 作为密钥,对 signatureBaseString 计算 HMAC-SHA256 摘要。
  2. 将计算结果按约定编码。
  3. 将最终签名写入请求头:sign: <签名值>

防重放与校验

  • timestamp:仅在服务端允许的时间窗(例如 ±5 分钟)内有效。
  • nonce:服务端记录最近 N 分钟内的 nonce,重复的 nonce 将直接拒绝请求。

示例(完整举例)

已知条件

  • appId = test
  • appSecret = 123456
  • 请求 URL:https://fjgs-gateway.imageco.cn/open-api/member/verification?userId=286&price=2&bizType=11&bizId=2865&mode=1&note=11
  • nonce = e7eb4265-885d-40eb-ace3-2ecfc34bd635
  • timestamp = 1717494535932
  • 请求 body = 空字符串(raw body = ‘’)

计算步骤

  1. 处理 Query 参数
    解析并 decode 后得到对象:
    { bizId: "2865", bizType: "11", mode: "1", note: "11", price: "2", userId: "286" }
    按 key 字典序排序后拼接:
    sortedQueryString = "bizId=2865&bizType=11&mode=1&note=11&price=2&userId=286"

  2. 处理 Header 参数
    参与签名的 header 列表:['appId','nonce','timestamp']
    有效 header 及值:

    • appId=test
    • nonce=e7eb4265-885d-40eb-ace3-2ecfc34bd635
    • timestamp=1717494535932

    排序后拼接:
    sortedHeaderString = "appId=test&nonce=e7eb4265-885d-40eb-ace3-2ecfc34bd635&timestamp=1717494535932"

  3. 拼接签名基础串
    signatureBaseString = "bizId=2865&bizType=11&mode=1&note=11&price=2&userId=286&appId=test&nonce=e7eb4265-885d-40eb-ace3-2ecfc34bd635&timestamp=1717494535932&"

    注意:末尾的 & 因 body 为空保留,需与后端规则一致。

  4. 计算签名
    使用 HMAC-SHA256 算法,密钥为 123456,对 signatureBaseString 计算摘要并转 hex 小写:
    signature = hmac_sha256_hex("123456", signatureBaseString)

    (示例占位符:9a1b2c3d4e5f…,实际值需通过代码计算)

  5. 设置请求头
    将签名写入请求头:sign: 9a1b2c3d4e5f...

总结

  1. 签名计算需包含 query 参数、指定 header(appId/nonce/timestamp)、请求体 三类数据,且需与后端统一编码/排序/拼接规则。
  2. 签名核心是基于 appSecret 对规范化后的 signatureBaseString 执行 HMAC-SHA256 计算,并按约定编码。
  3. 防重放依赖 timestamp 时间窗和 nonce 唯一性校验,需确保每次请求的 nonce 唯一、timestamp 有效。