1. 签名方法
以下文档说明了请求签名的签名过程,但仅在您编写自己的代码来调用 智算云平台 API 时才有用。
我们推荐您使用 智算云平台提供好的 SDK/CLI 等工具调用 API。
智算云平台 API 会对每个请求进行身份验证,用户需要使用密钥对,经过特定的步骤对请求进行签名(Signature),每个请求都需要在公共参数中指定该签名结果并以指定的方式和格式发送请求。
1.1. 为什么要进行签名
签名通过以下方式帮助保护请求:
- 验证请求者的身份。
- 保护传输中的数据
请从【智算云平台】->【个人中心】获取密钥相关信息。
为了防止请求在传输过程中被篡改,智算云平台 API 会使用请求参数来计算请求的哈希值,并将生成的哈希值加密后作为请求的一部分,发送到 智算云平台 API 服务器。
服务器会使用收到的请求参数以同样的过程计算哈希值,并验证请求中的哈希值。如果请求被篡改,将导致哈希值不一致,智算云平台 API 将拒绝本次请求。
1.2. 申请密钥对
本文使用的密钥对为密钥,密钥包括 AccessKey 和 SecretAccessKey。
每个用户可以拥有多个密钥对,不同的密钥对拥有不同的访问权限。
- AccessKey:用于标识 API 调用者身份,可以简单类比为用户名。
- SecretAccessKey:用于验证 API 调用者的身份,可以简单类比为密码。
用户必须严格保管密钥对,避免泄露,否则将危及财产安全。如已泄露,请立刻禁用该密钥对。
1.3. 签名过程
智算云平台 API 支持 GET 和 POST 请求。
目前对于 GET/POST 方法,只支持 Content-Type: application/json 一种协议格式。
以下以云服务器实例查询列表作为例子,介绍签名的计算过程。
我们选择该接口是因为:
- 云服务器默认已开通,该接口很常用;
- 该接口是只读的,不会改变现有资源的状态;
- 接口覆盖的参数种类较全,可以演示包含数据结构的数组如何使用。
注意:
以下内容中涉及到的文本和代码只用于描述如何进行访问的签名,不作为实际请求的依据。 建议请调用 智算云平台提供的 SDK 进行资源的操作和资源信息的获取
假设用户的 AccessKey 和 SecretAccessKey 分别是:
AccessKey: 9fed355d05d863cd70d7015ba36274dd
SecretAccessKey: OWZlZDM1NWQwNWQ4NjNjZDcwZDcwMTViYTM2Mjc0ZGQ
用户想查看其账户未被删除的中卫云服务器列表信息,则请求可能为:
curl -X POST https://ai.blsc.cn/v3/instance/DescribeInstances \
-H "Content-Type: application/json; charset=utf-8" \
-H "Host: ai.blsc.cn" \
-H "X-TC-Version: V3" \
-H "X-TC-Action: DescribeInstances" \
-H "X-TC-Timestamp: 1696748400" \
-H "X-TC-Accesskey: 9fed355d05d863cd70d7015ba36274dd" \
-H "X-TC-Signedheaders: content-type;host" \
-H "X-TC-Signature: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-d '{"pageNum":1,"pageSize":5,"deleteStatus":"NotDeleted"}'
下面详细解释签名计算过程。
1.3.1. 拼接规范请求串
按如下伪代码格式拼接规范请求串(CanonicalRequest):
CanonicalRequest =
HTTPRequestMethod + '\n' +
CanonicalURI + '\n' +
CanonicalQueryString + '\n' +
CanonicalHeaders + '\n' +
SignedHeaders + '\n' +
HashedRequestPayload
字段名称 | 解释 |
---|---|
HTTPRequestMethod | HTTP 请求方法(GET,POST) |
CanonicalURI | URI 参数,API v3 固定为正斜杠 (/) |
CanonicalQueryString | 发起 HTTP 请求 URL 中的查询字符串,对于 POST 请求,固定为空字符串"",对于 GET 请求,则为 URL 中问号(?)后面的字符串内容,例如:Limit=10&Offset=0 |
CanonicalHeaders | 参与签名的头部信息,至少包含 host 和 content-type 两个头部,也可加入其他头部参与签名以提高自身请求的唯一性和安全性,此示例额外增加了接口名头部 |
SignedHeaders | 参与签名的头部信息,说明此次请求有哪些头部参与了签名,和 CanonicalHeaders 包含的头部内容是一一对应的。content-type 和 host 为必选头部 |
HashedRequestPayload | 请求正文requestBody的哈希值。计算伪代码为 Lowercase(HexEncode(Hash.SHA256(RequestPayload)))。即对 HTTP 请求正文做 SHA256 哈希,然后十六进制编码,最后编码串转换成小写字母。对于 GET 请求,RequestPayload 固定为空字符串。此示例计算结果是 35e9c5b0e3ae67532d3c9f17ead6c90222632e5b1ff7f6e89887f1398934f064 |
CanonicalQueryString 注意事项:
CanonicalQueryString 需要参考 RFC3986 进行 URLEncode,字符集 UTF-8,推荐使用编程语言标准库,所有特殊字符均需编码,小写形式。
CanonicalHeaders 拼接规则:
- 头部 key 和 value 统一转成小写,并去掉首尾空格,按照 key:value\n 格式拼接。最后不加\n
- 多个头部,按照头部 key(小写)的 ASCII 升序进行拼接。
- 此示例计算结果是 content-type:application/json; charset=utf-8\nhost:ai.blsc.cn。
- 注意:content-type 必须和实际发送的相符合,有些编程语言网络库即使未指定也会自动添加 charset 值,如果签名时和发送时不一致,服务器会返回签名校验失败。
- Host 后的值需要去掉端口
SignedHeaders 拼接规则:
- 头部 key 统一转成小写;
- 多个头部 key(小写)按照 ASCII 升序进行拼接,并且以分号(;)分隔。
- 此示例为 content-type;host
根据以上规则,示例中得到的规范请求串如下:
POST
/
content-type:application/json; charset=utf-8
host:ai.blsc.cn
content-type;host
35e9c5b0e3ae67532d3c9f17ead6c90222632e5b1ff7f6e89887f1398934f064
1.3.2. 拼接待签名字符串
按如下格式拼接待签名字符串:
StringToSign =
Algorithm + \n +
Version + \n +
AccessKey + \n +
Service + \n +
CredentialScope + \n +
HashedCanonicalRequest
字段名称 | 解释 |
---|---|
Algorithm | 签名算法,目前固定为 HmacSHA256 |
Version | 签名版本。目前只支持 V3 |
AccessKey | 用户 AccessKey 唯一标识 |
Service | 所属服务。地域服务 region ;产品规格服务 production;云服务器实例服务是 ecs;云盘是 ebs;公网 IP 是 eip |
CredentialScope | 凭证范围。默认的拼装格式为 paratera/aicloud/${SERVICE} |
HashedCanonicalRequest | 前述步骤拼接所得规范请求串的哈希值,计算伪代码为 Lowercase(HexEncode(Hash.SHA256(CanonicalRequest)))。此示例计算结果是 7019a55be8395899b900fb5564e4200d984910f34794a27cb3fb7d10ff6a1e84 |
根据以上规则,示例中得到的待签名字符串如下:
HMAC-SHA256
V3
9fed355d05d863cd70d7015ba36274dd
ecs
paratera/aicloud/ecs
7019a55be8395899b900fb5564e4200d984910f34794a27cb3fb7d10ff6a1e84
1.4. 计算签名
1.4.1. 计算签名
伪代码如下所示:
SecretAccessKey = "OWZlZDM1NWQwNWQ4NjNjZDcwZDcwMTViYTM2Mjc0ZGQ"
Signature = HexEncode(HMAC_SHA256("BC_SIGNATURE&"+SecretAccessKey, StringToSign))
此示例计算结果是 be4f67d323c78ab9acb7395e43c0dbcf822a9cfac32fea2449a7bc7726b770a3。