CDN加速

接口鉴权V3

更新时间:2021-06-02 11:07:40

目录


接口鉴权v3相比另外两种鉴权两种,更安全。原两种接口鉴权方式依然可以用,推荐使用该鉴权方式。
下面以云点播的批量获取视频列表信息接口为例,对该鉴权方式进行示例说明

请求URL

以https://api.cloudv.haplat.net后拼接具体接口的URI参数

例如获取视频列表的请求URL如下

https://api.cloudv.haplat.net/vod/videoManage/getVideoList

请求方式

支持GET和POST请求

个别接口支持content-type: application/json的POST请求。

公共参数

该鉴权方式使用请求参数的以下字段:

参数名             类型 是否必填 描述
X-WS-AccessKey string       是       访问密钥ID(AccessKey ID)。对应的AccessKey Secret通过控制台的AccessKey管理界面获得。主账号和子账号都具有不同的AccessKey ID。服务端会对其授权范围进行校验,账号只能操作其有权限操作的数据。
X-WS-Timestamp int 秒级时间戳。
如果该时间与服务器时间相差超过5分钟,则该请求失效。
Authorization string HTTP标准身份认证头部字段,例如:
“WS3-HMAC-SHA256 Credential=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,SignedHeaders=content-type;host, Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024”
其中,
- WS3-HMAC-SHA256:签名方法,目前固定取该值;
- Credential:签名凭证,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 是 X-WS-AccessKey;
- SignedHeaders:参与签名计算的头部信息,content-type 和 host 为必选头部;
- Signature:签名摘要。校验凭证,由所有参数计算而得,详见下文的签名计算过程(加链接)。 同一X-WS-Timestamp,5分钟内Authorization不允许重复
content-Type string 向服务器实际发送的数据类型。如果是通过get请求调用,那么该参数值固定为"application/x-www-form-urlencoded"开头
host string 请求域名,固定为请求的域名,“api.cloudv.haplat.net”

签名(Sinature)计算过程

算法综述

  1. Signature=HexEncode(HMAC_SHA256(SecretKey, StringToSign));
  2. Stringtosign=Algorithm+\n+Timestamp+\n+Hash.SHA256(CanonicalRequest)
  3. CanonicalRequest=
    Method+’\n’+
    RequestURI+’\n’+
    QueryString+’\n’+
    CanonicalHeaders+’\n’+
    SignedHeaders+’\n’+
    HashedRequestPayload
  4. HashedRequestPayload= Lowercase(HexEncode(Hash.SHA256(RequestPayload)))

1. 拼接规范请求串(CanonicalRequest)

按如下伪代码格式拼接规范请求串(CanonicalRequest):

CanonicalRequest =
    Method + '\n' +
    RequestURI + '\n' +
    QueryString + '\n' +
    CanonicalHeaders + '\n' +
    SignedHeaders + '\n' +
    HashedRequestPayload

字段名称 解释
Method HTTP 请求方法(GET、POST )。此示例取值为 POST,注意这里的字符为大写。
RequestURI URI 参数,对于批量获取视频接口,该参数的值为/vod/videoManage/getVideoList
QueryString 发起 HTTP 请求 URL 中的查询字符串,对于 POST 请求,固定为空字符串"",
对于 GET 请求,则为 URL 中问号(?)后面的字符串内容,例如:“videoName=testVideoName&pageIndex=2&pageSize=5”。
CanonicalHeaders 参与签名的头部具体信息,至少包含 host 和 content-type 两个头部,也可加入自定义的头部参与签名以提高自身请求的唯一性和安全性。
拼接规则:
1. 头部 key 和 value 统一转成小写,并去掉首尾空格,按照 key:value\n 格式拼接;
2. 多个头部,按照头部 key(小写)的 ASCII 升序进行拼接。此示例计算结果是 “content-type:application/json; charset=utf-8\nhost:api.cloudv.haplat.net\n”。
注意:content-type 必须和实际发送的相符合,有些编程语言网络库即使未指定也会自动添加 charset 值,如果签名时和发送时不一致,服务器会返回签名校验失败。
SignedHeaders 参与签名的头部,说明此次请求有哪些头部参与了签名,和 CanonicalHeaders 包含的头部具体信息一一对应。content-type 和 host 为必选头部。
拼接规则:
1. 头部 key 统一转成小写;
2. 多个头部 key(小写)按照 ASCII 升序进行拼接,并且以分号(;)分隔。此示例为 “content-type;host”。
HashedRequestPayload 请求正文(即有效载荷payload或body)的哈希值。
如以content-type: application/json的格式传参,则示例为 {“videoName”:“a”,“pageSize”:“5”,“pageIndex”:“2”}的哈希值;
如以Content-Type: application/x-www-form-urlencoded的POST请求方式传参,则示例为 "videoName=a&pageIndex=2&pageSize=5"的哈希值;
计算伪代码为 Lowercase(HexEncode(Hash.SHA256(RequestPayload))),即对 HTTP 请求正文做 SHA256 哈希,然后十六进制编码,最后编码串转换成小写字母。
对于 GET 请求,RequestPayload 固定为空字符串。
此示例计算结果是 135b13e1b15e3c836eab2ab9196a86e7bcdb7b68da27215175a65b89ade3587e。

根据以上规则,示例中得到的规范请求串CanonicalRequest如下:

POST
/vod/videoManage/getVideoList

content-type:application/json; charset=utf-8
host:api.cloudv.haplat.net

content-type;host
641f7989f8d223af8c5049f805890fcaf2ae4a99780a01eb454cf7c9368dd1a4

2. 拼接待签名字符串(StringToSign)

按如下格式拼接待签名字符串:

StringToSign =

    Algorithm + \n +

    Timestamp + \n +

    HashedCanonicalRequest
字段名称 解释
Algorithm 签名算法,目前固定为 “WS3-HMAC-SHA256”。
Timestamp 请求时间戳,即请求头部的公共参数 X-WS-Timestamp 取值,取当前时间 UNIX 时间戳,精确到秒。此示例取值为 1564645579
HashedCanonicalRequest 前述步骤拼接所得规范请求串的哈希值,计算伪代码为 Lowercase(HexEncode(Hash.SHA256(CanonicalRequest)))。此示例计算结果是 “16bc1b4d4e6818f5aec2a7273cb2c3d3e4831fd61c6510222b9bec19bffac646”

注意:Timestamp 必须是当前系统时间,且需确保系统时间和标准时间是同步的,如果相差超过五分钟则必定失败。如果长时间不和标准时间同步,可能导致运行一段时间后,请求必定失败,返回签名过期错误。

根据以上规则,示例中得到的待签名字符串StringToSign如下:

WS3-HMAC-SHA256
1564645579
16bc1b4d4e6818f5aec2a7273cb2c3d3e4831fd61c6510222b9bec19bffac646

3. 计算签名(Signature)

1)获取签名密钥,例如:

SecretKey = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
字段名称 解释
SecretKey 原始的 AccessKey Secret

2)计算签名,伪代码如下:

Signature = HexEncode(HMAC\_SHA256(SecretKey, StringToSign))

4. 拼接 Authorization

按如下格式拼接 Authorization:

Authorization =
    Algorithm + ' ' +
    'Credential=' + AccessKey + ', ' +
    'SignedHeaders=' + SignedHeaders + ', ' +
    'Signature=' + Signature
字段名称 解释
Algorithm 签名方法,固定为 “WS3-HMAC-SHA256”。
AccessKey 密钥对中的 AccessKey Secret,从控制台“用户中心-AccessKey管理”页获取,本示例的值为 AKIDz8krbsJ5yKBZQpn74WFkmLPx3EXAMPLE。
SignedHeaders 见上文,参与签名的头部信息。此示例取值为 “content-type;host”
Signature 签名值。此示例计算结果是 “72e494ea809ad7a8c8f7a4507b9bddcbaa8e581f516e8da2f66e2c5a96525168”。

根据以上规则,示例中得到的值为:

WS3-HMAC-SHA256 Credential=AKIDz8krbsJ5yKBZQpn74WFkmLPx3EXAMPLE, SignedHeaders=content-type;host, Signature=792dcb6d648a456a030c9c6683fa7bde2a31cb4c72cfeaa354da000adf7c288d

最终完整的调用信息如下:

POST https://api.cloudv.haplat.net/
Authorization: WS3-HMAC-SHA256 Credential=AKIDz8krbsJ5yKBZQpn74WFkmLPx3EXAMPLE, SignedHeaders=content-type;host, Signature=792dcb6d648a456a030c9c6683fa7bde2a31cb4c72cfeaa354da000adf7c288d
Content-Type: application/json; charset=utf-8
Host: api.cloudv.haplat.net
X-WS-AccessKey: AKIDz8krbsJ5yKBZQpn74WFkmLPx3EXAMPLE
X-WS-Timestamp: 1564645579

{"videoName":"a","pageSize":"5","pageIndex":"2"}

通用错误码

错误码 描述
4001 鉴权参数错误,请检查所有必填参数是否都有传值
4002 X-WS-AccessKey参数错误,请检查该key是否存在,是否少复制了字符或者多了字符
4003 X-WS-Timestamp参数错误,时间格式为秒级时间戳
4004 X-WS-Timestamp过期,与服务器接收到请求的时间相差不得超过五分钟
4005 host参数错误,请检查
4006 content-type参数错误,请检查
4007 鉴权失败,请检查参数是否正确
4008 鉴权失败,请检查签名计算是否错误,或者签名与实际发送的内容不相符合,也有可能是密钥AccessKey Secret错误导致的
4009 签名已被使用,请重新生成鉴权参数

curl示例

content-type:application/json的post请求(推荐方式)

curl -X POST https://api.cloudv.haplat.net/vod/videoManage/getVideoList 
-H "Authorization: WS3-HMAC-SHA256 Credential=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, SignedHeaders=content-type;host, Signature=471d8f86cefa4fa2f929642207b6df8fe770e82e0df328f4f68af08c8b8a8029" 
-H "Content-Type: application/json; charset=utf-8" 
-H "Host: api.cloudv.haplat.net" 
-H "X-WS-Timestamp: 1564644606" 
-H "X-WS-AccessKey: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 
-d '{"videoName": "a","pageIndex":"2","pageSize":"5"}'

content-type:application/x-www-form-urlencoded的post请求

curl -X POST https://api.cloudv.haplat.net/vod/videoManage/getVideoList 
-H "Authorization: WS3-HMAC-SHA256 Credential=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, SignedHeaders=content-type;host, Signature=37ea1014de0c90e83e733f8d19a5d3ae993896d34450c9f8cf8df5642c81339e" 
-H "Content-Type: application/x-www-form-urlencoded; charset=utf-8" 
-H "Host: api.cloudv.haplat.net" 
-H "X-WS-Timestamp: 1564644607" 
-H "X-WS-AccessKey: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 
-d 'videoName=a&pageIndex=2&pageSize=5'

get请求

注意get请求里面Content-Type固定为application/x-www-form-urlencoded格式。

curl -X GET https://api.cloudv.haplat.net/vod/videoManage/getVideoList?videoName=a&pageIndex=2&pageSize=5 
-H "Authorization: WS3-HMAC-SHA256 Credential=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, SignedHeaders=content-type;host,     Signature=0b489e43c5cd2e52cbe0768a68c614a4211210a6d63b18ff65cc986f18e75aac" 
-H "Content-Type: application/x-www-form-urlencoded; charset=utf-8" 
-H "Host: api.cloudv.haplat.net" 
-H "X-WS-Timestamp: 1564644607" 
-H "X-WS-AccessKey: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

content-type:multipart/form-data的post请求

由于该请求的授权参数构造复杂,需要在代码中生成,请参考下面的java代码示例。

java代码示例

可通过引用工具类的方式使用api接,需引入until.jar包。

详细代码示例

import com.cnc.cloudv.util.auth.ApiAuthUtil;
import com.cnc.cloudv.util.httpclient.CloudvHttpResponse;

import java.util.HashMap;
import java.util.Map;

public class TestAuthUtil {
//通过秘钥管理获取的秘租
    private final static String ACCESS_KEY = "aaaaaaaaaaaaaaaaaaaaaaaaa";
    private final static String SECRET_KEY = "bbbbbbbbbbbbbbbbb";
//这里固定为云视频API域名
    private final static String API_HOST = "api.cloudv.haplat.net";

    public static void main(String[] args) throws Exception {
        Map<String, String> customHeaderMap = new HashMap<String, String>(2);
	//可以支持自定义头部
        customHeaderMap.put("from", "test-authentification-sdk");
		//请求接口的URI
        String requestURI = "/vod/videoManage/getVideoList";

	//application/json方式的post请求调用
        String body = "{\"videoName\": \"测\",\"pageIndex\":\"2\",\"pageSize\":\"5\",\"format\": \"json\"}";
        CloudvHttpResponse cloudvHttpResponse = ApiAuthUtil.callPostJsonBodyRequest(API_HOST, ACCESS_KEY, SECRET_KEY, requestURI, customHeaderMap, body);
        log(cloudvHttpResponse);
		
	//get请求的调用例子
        String canonicalQueryString = "videoName=" + java.net.URLEncoder.encode("测", "utf-8") + "&pageIndex=2&pageSize=5&format=json";
        cloudvHttpResponse = ApiAuthUtil.callGetRequest(API_HOST, ACCESS_KEY, SECRET_KEY, requestURI, customHeaderMap, canonicalQueryString);
        log(cloudvHttpResponse);

	//form-Urlencoded方式的post请求调用示例
        body = "videoName=" + java.net.URLEncoder.encode("测", "utf-8") + "&pageIndex=2&pageSize=5&format=json";
        cloudvHttpResponse = ApiAuthUtil.callPostFormUrlencodedBodyRequest(API_HOST, ACCESS_KEY, SECRET_KEY, requestURI, customHeaderMap, body);
        log(cloudvHttpResponse);
		
		
	//通过map方式传入URL参数的请求方式
        Map<String, String> map = new HashMap<String, String>();
        map.put("videoName", "测");
        map.put("pageIndex", "2");
        map.put("pageSize", "5");
        map.put("format", "json");
        cloudvHttpResponse = ApiAuthUtil.callPostFormUrlencodedBodyRequest(API_HOST, ACCESS_KEY, SECRET_KEY, requestURI, customHeaderMap, map);
        log(cloudvHttpResponse);

        System.out.print("调用完毕");

    }

    public static void log(CloudvHttpResponse cloudvHttpResponse) throws Exception {
	//每次请求统一会带上一个X-WS-RequestId用来方便排查问题
        System.out.println("返回结果是:" + cloudvHttpResponse + " , requestId = " + cloudvHttpResponse.getHeaders().get("X-WS-RequestId"));
    }

}