鉴权认证

简介

本文档主要针对需要集成HTTP API的技术研发工程师。

学而思网校AI教育开放平台HTTP API使用签名机制对每个接口请求进行权限校验,对于校验不通过的请求,API将拒绝处理,并返回鉴权失败错误。

接口调用者在调用API时必须带上接口请求签名,其中签名信息由接口请求参数和应用密钥根据本文提供的签名算法生成。

本文档提供 getReqSign(计算签名)、doHttpPost(执行HTTP POST调用)两个PHP实现的工具函数方便开发者参考。

鉴权介绍

1. 鉴权作用

通过可靠的数字签名算法,认证调用方信息,防止非授权调用,占用网络或计算资源,同时防止因账号泄露、恶意消费而给您带来不良影响。

2. 鉴权接入

鉴权凭据获取,参见新手指南
快速接入需要使用app_key。
安全接入方式中,必须使用 app_key 和 app_secret 生成签名,数字签名认证通过,方能正常调用服务。

出现错误码 14000 - 14004 时,请查看是否因字段缺失或错误,导致鉴权未通过。

签名算法

1. 计算步骤

用于计算签名的参数在不同接口之间会有差异,但算法过程固定如下4个步骤。

  1. 将<key, value>请求参数对按key进行字典升序排序,得到有序的参数对列表N
  2. 将列表N中的value依次拼接成一个字符串T无拼接符
  3. 在字符串T的末尾拼接您的App_secret得到字符串S
  4. 对字符串S进行sha1运算,得到接口请求签名

2. 注意事项

  • 不同接口要求的参数对不一样,计算签名使用的参数是一样的:都是 app_key,time_stamp,nonce_str,app_secret
  • App_secret字段应最后进行拼接
  • 签名有效期5分钟,需要请求接口时刻实时计算签名信息
  • 更多注意事项,请查看常见问题

3. 参考代码(PHP)

以下是使用PHP实现的签名算法代码,开发者可以参考实现其他语言的版本。

// getReqSign :根据 接口请求参数 计算 请求签名
// 参数说明
//   - $params:接口请求参数(特别注意:不同的接口,参数对一般不一样,请以具体接口要求为准)
// 返回数据
//   - 签名结果
function getReqSign($params, $app_secret)
{
    // 1. 字典升序排序
    ksort($params);

    // 2. 拼接value
    $str = '';
    foreach ($params as $key => $value)
    {
        $str .= $value;
    }
  
    // 3. 拼接App_secret
    $str .= $app_secret;

    // 4. sha1运算,得到请求签名
    $sign = sha1($str);
    return $sign;
}

接口调用示例

本示例仅供开发者参考,学习如何生成签名以及调用API

1. 示例数据

假设接口请求参数如下,app_key为:8102b22a5e81e840176d9f381ec6f837,app_secret为:f308ce31e42e366093c01e5283f1acc02c2cd47492f5c8633b55d58930be2b2c ,其中sign参数用于存储接口请求签名。

参数名 位置 参数值 备注 必选 其他
app_key query 8102b22a5e81e840176d9f381ec6f837 应用标识 通用鉴权参数
time_stamp query 1493468759 秒级别时间戳 通用鉴权参数
nonce_str query fa577ce340859f9fe 随机字符串,字符长度1-32,可以由数字和字母混搭 通用鉴权参数
sign query 9f1390bee8f15855e0dc73ecb8a6236ec5a61949 接口请求签名,待计算 通用鉴权参数
key1   value1 接口请求数据   业务参数
key2   value2 接口请求数据   业务参数

关于如何获取应用密钥,请查阅接入指南

2. 计算请求签名(sign)

上述接口请求参数除了sign参数,其他参数均已确定参数值。

此时按照签名算法要求,sign的计算代码如下。

// 接口请求参数
$params = array(
    'app_key'    => '8102b22a5e81e840176d9f381ec6f837',
    'time_stamp' => '1493468759',
    'nonce_str'  => 'fa577ce340859f9fe',
);
$app_secret = '8102b22a5e81e840176d9f381ec6f837';

// 计算sign参数(接口请求签名)
$params['sign'] = getReqSign($params, $app_secret);
$params['key1'] = 'value1';
$params['key2'] = 'value2';

// 得到所有请求参数
var_dump($params);

上述var_dump($params)的输出结果:

array (size=6)
  'app_key' => string '8102b22a5e81e840176d9f381ec6f837' (length=32)
  'time_stamp' => string '1493468759' (length=10)
  'nonce_str' => string 'fa577ce340859f9fe' (length=17)
  'sign' => string '9f1390bee8f15855e0dc73ecb8a6236ec5a61949' (length=40)
  'key1' => string 'value1' (length=2)
  'key2' => string 'value2' (length=2)

可知,sign的计算结果为9f1390bee8f15855e0dc73ecb8a6236ec5a61949。

3. 最终请求数据

在完成sign计算后,即可得到所有接口请求数据,开发者可进入下一步完成API的调用(构造HTTP请求)。

参数名 参数值 备注
app_key 8102b22a5e81e840176d9f381ec6f837 应用标识
time_stamp 1493468759 秒级别时间戳
nonce_str fa577ce340859f9fe 随机字符串
sign 9f1390bee8f15855e0dc73ecb8a6236ec5a61949 接口请求签名
key1 value1 接口请求数据
key2 value2 接口请求数据

4. 执行API调用(PHP)

假设该示例的接口API地址为:https://api.ai.xueersi.com/v1/api,请求方式要求为:POST。

此时通过PHP实现API的调用代码如下,开发者可以参考实现其他语言的版本。

// doHttpPost :执行POST请求,并取回响应结果
// 参数说明
//   - $url   :接口请求地址
//   - $params:完整接口请求参数(特别注意:不同的接口,参数对一般不一样,请以具体接口要求为准)
// 返回数据
//   - 返回false表示失败,否则表示API成功返回的HTTP BODY部分
function doHttpPost($url, $params)
{
    $curl = curl_init();

    $response = false;
    do
    {
        // 1. 设置HTTP URL (API地址)
        curl_setopt($curl, CURLOPT_URL, $url);

        // 2. 设置HTTP HEADER (表单POST)
        $head = array(
            'Content-Type: application/x-www-form-urlencoded'
        );
        curl_setopt($curl, CURLOPT_HTTPHEADER, $head);

        // 3. 设置POST数据 
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $params);

        // 4. 调用API,获取响应结果
        curl_setopt($curl, CURLOPT_HEADER, false);
        curl_setopt($curl, CURLOPT_NOBODY, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        $response = curl_exec($curl);
        if ($response === false)
        {
            $response = false;
            break;
        }

        $code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        if ($code != 200)
        {
            $response = false;
            break;
        }
    } while (0);

    curl_close($curl);
    return $response;
}

// 设置请求数据(应用密钥、接口请求参数)
$params = array(
    'app_key'    => '8102b22a5e81e840176d9f381ec6f837',
    'time_stamp' => '1493468759',
    'nonce_str'  => 'fa577ce340859f9fe',
);
$app_secret = 'f49922d511d666848f250663c4fca84074b856a8';
$params['sign'] = getReqSign($params, $app_secret);
$params['key1'] = 'value1';
$params['key2'] = 'value2';

// 执行API调用
$url = 'https://api.ai.xueersi.com/v1/api';
$response = doHttpPost($url, $params);
echo $response;

上述echo $response的输出结果即API的响应结果:

{
  "code": 0,
  "msg": "请求成功",
  "data": {}
}
Back to top