直播云提供各类API让客户开发的应用使用直播云的服务,客户开发的应用访问这些API时需要提供凭证,这个凭证就是签名,通过签名直播云可以确认客户的身份以及合法性,防止非法程序恶意调用API。
直播云提供的API都是基于HTTP服务的,所以API调用方是通过HTTP Header把签名认证信息传给直播云的。
所有发出的API请求,都必须包含以下两个头:
xvs-timestamp
xvs-signature
直播云除了验证签名,也会验证访问请求的时间戳是否合法。
发出的API请求要带上当前的时间戳。云端收到请求后会判断请求的时间戳与当前标准时间的差值是否在合理范围内,如果差值超过300秒(5分钟)即认为此请求是非法的,因此所有发出API请求的主机都需要和标准时间同步步, 否则可能会由于时间问题而导致请求被拒绝。
时间戳需要考虑时区的影响,原理是这样的:同样一个字符串
2015-01-01 08:00:00
在默认时区设置为0时区的机器上表示的是GMT时间2015-01-01 08:00:00,而在默认时区设置为+8时区的机器上表示的GMT时间却为2015-01-01 00:00:00
, 所以加上了时区的时间字符串才能准确地表示时间。
以下时间戳的表示方法都是正确的, 并且都是表示的东八区时间: 2015年6月22日15:41:43
序号 | 示例 | 说明 |
---|---|---|
1 | 1434958903145 | Unix时间戳, 表示零时区下自1970-01-01起过去的时间,单位是ms 建议用这种格式 |
2 | Mon Jun 22 2015 15:41:43 GMT+0800 (CST) | 可读的带有时区表达的时间 |
3 | 2015-06-22T07:41:43+0000 | YYYYMMDDTHHmmss格式, 带有时区表标志,表明为0时区 |
4 | 2015-06-22T15:41:43+0800 | 带有时区表标志, 表明为+8时区 |
5 | 2015-06-22T07:41:43 | 不带时区标志,默认为UTC零时区 不建议使用此方式 |
建议用1方式,因为这种方法最简单,而且一般语言都有API支持,2方式也是由开发语言API直接返回的带有时区标志字串。不建议自己去格式化字符串,因为自己格式化字符串需要知道当前系统所设置的时区。
xvs-signature就是签名。
签名的具体算法是把请求url中的uri 和 请求参数串(包含&)和 xvs-timestamp字段内容相连后的字串做sha256 HMAC运算。
签名的Javascript算法如下:
var sha256_signer = crypto.createHmac('sha256', key); //注: key就是密钥字符串
sha256_signer.update(uri + data + header_timestamp, 'utf8').digest('hex');
签名的php算法如下:
$header_timestamp = date("Y-m-d\TH:i:s", time());
hash_hmac( "sha256", utf8_encode($uri.$data.$header_timestamp), utf8_encode($key)); //注: $key就是密钥字符串
解释如下:
输入参数:
http://c.zhiboyun.com/api/20140928/task_list
,则uri的值为 /api/20140928/task_list
某个API请求抓包数据如下:
GET /api/20140928/task_list?service_code=TESTING HTTP/1.1
Host: c.zhiboyun.com
Connection: keep-alive
Accept: application/json, text/javascript, */*; q=0.01
xvs-timestamp: 1443183207537
xvs-signature: ed92a6b07931b849ace52e6f3fa38718e0f949500070620e7e4f3432a4c96193
上面的请求中:
uri: /api/20140928/task_list
data: service_code=TESTING
xvs-timestamp: 1443183207537
共享密钥为:abc
由上述参数和signature的公式计算出:
xvs-signature: ed92a6b07931b849ace52e6f3fa38718e0f949500070620e7e4f3432a4c96193
用php算法计算即为:
hash_hmac( "sha256", utf8_encode("/api/20140928/task_listservice_code=TESTING1443183207537"), utf8_encode('abc'));