签名算法

为了防止 API 调用过程中被黑客恶意篡改,调用任何一个 API 都需要携带签名,框架会根据请求参数,对签名进行验证,签名不合法的请求将会被拒绝。签名大体过程如下:

  • 对所有 API 请求参数(包括公共参数和业务参数,但除去sign参数和byte[]类型的参数),根据参数名称的 ASCII 码表的顺序排序。如:foo:1,bar:2,foo_bar:3,foobar:4排序后的顺序是bar:2,foo:1,foo_bar:3,foobar:4
  • 将排序好的参数名和参数值拼装在一起,根据上面的示例得到的结果为:bar2foo1foo_bar3foobar4
  • 把拼装好的字符串采用utf-8编码,再在拼装的字符串前后加上app_secret,之后进行摘要,如:md5(app_secret+bar2foo1foo_bar3foobar4+app_secret)

MD5 是 128 位长度的摘要算法,用 16 进制表示,一个十六进制的字符能表示 4 个位,所以签名后的字符串长度固定为 32 个十六进制字符,并且需转为小写字母

PHP 签名示例代码

  1. private function sign()
  2. {
  3. // 获取app_secret
  4. $appSecret = "xxx";
  5. // 获取所有参数
  6. $params = $this->params;
  7. // 去除sign参数
  8. unset($this->params['sign']);
  9. // 将参数Key按字典顺序排序
  10. ksort($params);
  11. // 准备拼装的字符串前加入app_secret值
  12. $stringToBeSigned = $appSecret;
  13. // 取出参数名和参数值进行拼装,但过滤掉byte[]类型的参数
  14. foreach ($params as $k => $v) {
  15. if (is_string($v) && '@' != substr($v, 0, 1)) {
  16. $stringToBeSigned.= "$k$v";
  17. }
  18. }
  19. unset($k, $v);
  20. // 在拼装的字符串尾部加入app_secret值
  21. $stringToBeSigned.= $appSecret;
  22. // MD5摘要后返回
  23. return md5($stringToBeSigned);
  24. }

调用示例

get.app.list调用为例,具体步骤如下:

  1. 设置参数值

    • 公共参数:
      1. method = "get.app.list"
      2. appkey = "12345678"
      3. token = "test"
      4. timestamp = "1523553249"
      5. format = "json"
    • 业务参数:
      1. app_name = "ios"
      2. status = 1
  2. 按 ASCII 顺序排序

    1. app_name = "ios"
    2. appkey = "12345678"
    3. format = "json"
    4. method = "get.app.list"
    5. status = 1
    6. timestamp = "1523553249"
    7. token = "test"
  3. 拼接参数名与参数值

    1. app_nameiosappkey12345678formatjsonmethodget.app.listtimestamp1523553249tokentest
  4. 生成签名 假设app_secret的值为careyshop,与第 3 步的字符串再进行拼接:

    1. md5('careyshop' + 'app_nameiosappkey12345678formatjsonmethodget.app.listtimestamp1523553249tokentest' + 'careyshop');

    最终的签名字符串是:694d5cee85def32fac63bd6c1896c41c

  5. 组装 HTTP 请求 将所有参数名和参数值采用utf-8进行URL编码(参数顺序可随意,但必须要包括签名参数),然后通过GETPOST(含byte[]类型参数)发起请求,如:

    1. https://host/api/v1/app/appkey/12345678/token/test/timestamp/1523553249/format/json/method/get.app.list/app_name/ios/status/1/sign/694d5cee85def32fac63bd6c1896c41c/