更新时间:2021-07-30 15:35:59
对于每一次HTTP或者HTTPS协议请求,网宿云会根据访问中的签名信息验证访问请求者身份。具体主要由使用AccessKeySecret、签名算法类型、请求时间戳和请求规范化字符串进行数据加密。
AccessKeyID和AccessKeySecret可在控制台AccessKey管理页面获得。
AccessKeyID:访问者身份
AccessKeySecret:加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密谨防泄露。
以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” |
按如下伪代码格式拼接规范请求串(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
按如下格式拼接待签名字符串:
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
1)获取签名密钥,例如:
SecretKey = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
字段名称 | 解释 |
---|---|
SecretKey | 原始的 AccessKey Secret |
2)计算签名,伪代码如下:
Signature = HexEncode(HMAC\_SHA256(SecretKey, StringToSign))
按如下格式拼接 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 -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"}'
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请求里面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"
由于该请求的授权参数构造复杂,需要在代码中生成,请参考下面的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"));
}
}