对于每一次HTTP或者HTTPS协议请求,我们会根据访问中的签名信息验证访问请求者身份。具体由使用AccessKeyID和AccessKeySecret对称加密验证实现,AccessKeyID和AccessKeySecret在会员中心->AccessKey管理获得。

1. 指定请求参数

在代码中指定请求参数,参数中需要包含公共请求头和接口必备的参数信息。

指定参数(PHP)示例代码如下:

    $array                    = [];
    $array['AccessKeyID']     = 'testid';
    $array['InputCharset']    = 'UTF-8';
    $array['SignatureMethod'] = 'MD5';
    $array['Format']          = 'json';
    $array['Timestamp']       = '2019-12-12 20:19:05';
    $array['attach']          = 'userid=text';

说明:不应许出现Signature作为Key出现,Signature不在签名范围。

2. 根据参数Key排序(顺序)

    // 将参数Key按字典顺序排序
    ksort($array);

3. 构造签名字符串

编码参数。使用UTF-8字符集按照RFC3986规则编码请求参数和参数取值,编码规则如下:

  1. 字符A~Z、a~z、0~9以及字符-、_、.、~不编码。

  2. 其它字符编码成%XY的格式,其中XY是字符对应ASCII码的16进制。示例:半角双引号(")对应%22。

  3. 扩展的UTF-8字符,编码成%XY%ZA…的格式。

  4. 空格( )编码成%20,而不是加号(+)。

  5. 该编码方式与application/x-www-form-urlencodedMIME格式编码算法相似,但又有所不同,使用urlencode编码后,将"+","*","%7E"做替换即满足ECS API规定的编码规范。

    /**
     * 替换特征字符
     * 使用urlencode编码后,将"+","*","%7E"做替换即满足ECS API规定的编码规范
     */
    function percent_encode($str) {
        $res = urlencode($str);
        $res = preg_replace('/\+/', '%20', $res);
        $res = preg_replace('/\*/', '%2A', $res);
        $res = preg_replace('/%7E/', '~', $res);
        return $res;
    }

    $str = '';
    foreach ($array as $key => $value) {
        $str .= '&' . percent_encode($key) . '=' . percent_encode($value);
    }

生成规范化请求字符串示例如下:

&AccessKeyID=testid&Format=json&InputCharset=UTF-8&SignatureMethod=sha1&Timestamp=2019-12-12%2020%3A19%3A05&attach=userid%3Dtext

删除左右&符号:

AccessKeyID=testid&Format=json&InputCharset=UTF-8&SignatureMethod=sha1&Timestamp=2019-12-12%2020%3A19%3A05&attach=userid%3Dtext

计算签名

假设您获得了AccessKeyID=testid以及AccessKeySecret=testsecret,签名流程如下所示:

//拼接AccessKeySecret
$str = AccessKeyID=testid&Format=json&InputCharset=UTF-8&SignatureMethod=sha1&Timestamp=2019-12-12%2020%3A19%3A05&attach=userid%3Dtext&testsecret

//MD5签名
$sign = md5($str);

//输出结果:f542f6e1c096e644ba8235336f27d1c4


完整PHP代码示例

    /**
     * 替换特征字符
     * 使用urlencode编码后,将"+","*","%7E"做替换即满足ECS API规定的编码规范
     */
    function percent_encode($str) {
        $res = urlencode($str);
        $res = preg_replace('/\+/', '%20', $res);
        $res = preg_replace('/\*/', '%2A', $res);
        $res = preg_replace('/%7E/', '~', $res);
        return $res;
    }

    
    
    /**
     * 生成签名
     */
    function compute_signature($data, $accessKeySecret, $signature_method = 'sha1') {
        $signature_method = strtolower($signature_method);
        // 将参数Key按字典顺序排序
        ksort($data);
        // 生成规范化请求字符串
        foreach ($data as $key => $value) {
            $str .= '&' . percent_encode($key) . '=' . percent_encode($value);
        }
        //删除左右&符号
        $str = trim($str, '&');
        //拼接AccessKeySecret
        $str .= '&' . $accessKeySecret;
        $sign = $signature_method == 'sha1' ? sha1($str) : md5($str);
        return $sign;
    }
    

    //请求参数
    $array                    = [];
    $array['AccessKeyID']     = 'testid';
    $array['InputCharset']    = 'UTF-8';
    $array['SignatureMethod'] = 'MD5';
    $array['Format']          = 'json';
    $array['Timestamp']       = '2019-12-12 20:19:05';
    $array['attach']          = 'userid=text';

    //生成签名
    $array['sign'] = compute_signature($array, 'testsecret');
    
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, 'http://api.aimlt.com');
    curl_setopt($curl, CURLOPT_HEADER, 1);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    //设置post方式提交
    curl_setopt($curl, CURLOPT_POST, 1);
    //设置post数据
    curl_setopt($curl, CURLOPT_POSTFIELDS, $array);
    //执行命令
    $data = curl_exec($curl);
    curl_close($curl);
    print_r($data);