跳转至

API 加密规则详解

最新更新时间:2021.09.15

巨量 API 会对每个访问请求进行身份验证,即每个请求都需要包含签名信息(sign参数)以验证请求者身份。 签名信息由安全凭证生成,安全凭证包括 业务号(trade_no) 和 API Key;每个业务都有对应的API Key(请到业务管理中具体业务中获取),API Key相当于调用API的密码,一定要严格保密谨防泄露。


重要提示

巨量Api的所有接口调用全部使用HTTPS加密传输,调用接口也使用加密签名验签来确保您的信息安全。

1. 加密演示

为演示方便,此处虚构一个业务编号和key,为的是方便演示,在使用的使用过程中,需要您使用自己的业务编号和key。下面演示动态代理提取10个代理IP,附带城市名称和剩余可用时长,以Json格式返回的参数示例

  • trade_no(业务编号):1483587531995538
  • num(提取数量):10
  • city_name(城市名称):1
  • ip_remain(剩余可用时长):1
  • result_type(数据返回格式):json
  • key(业务密钥):99064631962e4e838dac1143092f6112

1.1 参数排序

首先对所有请求参数按参数名的字典序( ASCII 码)升序排序。注意:

  1. 只按参数名进行排序,参数值保持对应即可,不参与比大小;
  2. 按 ASCII 码比大小,如 InstanceIds.2 要排在 InstanceIds.12 后面,不是按字母表,也不是按数值。用户可以借助编程语言中的相关排序函数来实现这一能,如 php 中的 ksort 函数。 上述示例参数的排序结果如下:
city_name=1&num=10&ip_remain=1&result_type=json&trade_no=1178311789392776

使用其它程序设计语言开发时,可对上面示例中的参数进行排序,得到的结果一致即可。

1.2 拼接签名原文字符串

此步骤生成签名原文字符串。 签名原文字符串由以下几个参数构成:

签名原文串的拼接规则为:

示例的拼接结果为:

city_name=1&num=10&ip_remain=1&result_type=json&trade_no=1178311789392776&key=99064631962e4e838dac1143092f6112

1.3 生成加密字符串

此步骤生成签名串。使用 MD5 算法对上一步中获得的签名原文字符串进行签名,即可获得最终的签名串。

具体代码如下,以 PHP 语言为例:

<?php
$rawStr = 'city_name=1&num=10&ip_remain=1&result_type=json&trade_no=1178311789392776&key=99064631962e4e838dac1143092f6112';
echo md5($rawStr);

最终得到的签名串为:

MD5 使用32位小写格式
73fabf914b46cf91a0cce9e8e471b2a6

1.4 生成Api链接示例

此处以动态代理提取IP的接口为例。

最后输出的链接为:

http://v2.api.juliangip.com/dynamic/getips?city_name=1&num=10&ip_remain=1&result_type=json&trade_no=1178311789392776&sign=73fabf914b46cf91a0cce9e8e471b2a6

2. 代码示例

提示

PHP生成请求字符串示例

  1. 在下面的示例中,不同编程语言,甚至同一语言每次执行得到的 url 可能都有所不同,表现为参数的顺序不同,但这并不影响正确性。只要所有参数都在,且签名计算正确即可。
  2. 其他语言示例请参考
<?php
class SignKit {

    protected static $postCharset = "UTF-8";
    protected static $fileCharset = "UTF-8";

    /**
     * MD5 加密
     * @param $params
     * @param $secret
     * @return string
     */
    public static function md5Sign($params,$secret): string
    {
        return md5(self::getSignContent($params) . '&key=' . $secret);
    }



    protected static function getSignContent($params): string
    {
        unset($params['sign']); // 删除Sign
        ksort($params);
        $stringToBeSigned = "";
        $i = 0;
        foreach ($params as $k => $v) {
            if (false === self::checkEmpty($v) && "@" != substr($v, 0, 1)) {
                // 转换成目标字符集
                $v = self::character($v, self::$postCharset);
                if ($i == 0) {
                    $stringToBeSigned .= "$k" . "=" . "$v";
                } else {
                    $stringToBeSigned .= "&" . "$k" . "=" . "$v";
                }
                $i++;
            }
        }
        unset ($k, $v);
        return $stringToBeSigned;
    }


    /**
     * 转换字符集编码
     * @param $data
     * @param $targetCharset
     * @return string
     */
    protected static function character($data, $targetCharset): string
    {
        if (!empty($data)) {
            $fileType = self::$fileCharset;
            if (strcasecmp($fileType, $targetCharset) != 0) {
                $data = mb_convert_encoding($data, $targetCharset);
            }
        }
        return $data;
    }


    /**
     * 校验$value是否非空
     *  if not set ,return true;
     *    if is null , return true;
     **/
    protected static function checkEmpty($value): bool
    {
        if (!isset($value))
            return true;
        if (trim($value) === "")
            return true;
        return false;
    }
}
// 下面为生成示例
$key = "99064631962e4e838dac1143092f6112";
$rawStr = [
        'trade_no'  =>  '1483587531995538',
        'num'       =>  10,
        'city_name' =>  1,
        'remain'        =>  1,
        'result_type'   =>  'json',
    ];
$sign = SignKit::md5Sign($params, $key);
echo http_build_query($params)."&sign=".$sign;
Back to top