二、1. 服务地址(endpoint)
API 支持就近地域接入(例如:CVM 产品域名为 cvm.tencentcloudapi.com),也支持指定地域域名访问(例如:广州地域的域名为 cvm.ap-guangzhou.tencentcloudapi.com)。各产品支持地域不同,具体可参考产品文档的地域列表。例如,云服务器可参见 地域列表。
注意:对时延敏感的业务,建议指定带地域的域名。
三、2. 通信协议
腾讯云 API 的所有接口均采用 HTTPS 方式进行通信,提供高安全性的通信通道。
四、3. 请求方法
支持的 HTTP 请求方法:
·POST(推荐)
·GET
POST 请求支持的 Content-Type 类型:
·application/json(推荐),必须使用签名方法 v3(TC3-HMAC-SHA256)。
·application/x-www-form-urlencoded,必须使用签名方法 v1(HmacSHA1 或 HmacSHA256)。
·multipart/form-data(仅部分接口支持),必须使用签名方法 v3(TC3-HMAC-SHA256)。
注意:GET 请求的请求包大小不得超过32KB。POST 请求使用签名方法 v1(HmacSHA1、HmacSHA256)时不得超过1MB。POST 请求使用签名方法 v3(TC3-HMAC-SHA256)时最大支持10MB。
五、4. 字符编码
均使用 UTF-8 编码。
六、公共参数
注意:说明:
注意:公共参数是用于标识用户和接口签名的参数,每次请求均需要携带这些参数,才能正常发起请求。
七、签名方法 V3公共参数
签名方法 v3(有时也称作 TC3-HMAC-SHA256)相比签名方法 v1 (部分文档简称为“签名方法”),更安全,支持更大的请求包,支持 POST JSON 格式,性能有一定提升,推荐使用该签名方法计算签名。使用方法见下文 “签名方法介绍” 。
| 参数名称 | 类型 | 必选 | 描述 |
| X-TC-Action | String | 是 | 操作的接口名称。取值参考接口文档中输入参数公共参数 Action 的说明。例如云服务器的查询实例列表接口,取值为 DescribeInstances。 |
| X-TC-Region | String | – | 地域参数,用来标识希望操作哪个地域的数据。接口接受的地域取值参考接口文档中输入参数公共参数 Region 的说明。注意:某些接口不需要传递该参数,接口文档中会对此特别说明,此时即使传递该参数也不会生效。 |
| X-TC-Timestamp | Integer | 是 | 当前 UNIX 时间戳,可记录发起 API 请求的时间。例如1529223702。注意:如果与服务器时间相差超过5分钟,会引起签名过期错误。 |
| X-TC-Version | String | 是 | 操作的 API 的版本。取值参考接口文档中入参公共参数 Version 的说明。例如云服务器的版本2017-03-12。 |
| Authorization | String | 是 | HTTP 标准身份认证头部字段,例如: TC3-HMAC-SHA256 Credential=AKIDEXAMPLE/Date/service/tc3_request, SignedHeaders=content-type;host, Signature=72e494ea8******************************************a96525168 其中:TC3-HMAC-SHA256:签名方法,目前固定取该值。Credential:签名凭证,AKIDEXAMPLE 是 SecretId。Date 是 UTC 标准时间的日期,取值需要和公共参数 X-TC-Timestamp 换算的 UTC 标准时间日期一致。service 为产品名,通常为域名前缀,例如域名 cvm.tencentcloudapi.com 意味着产品名是 cvm。本产品取值为 cvm。SignedHeaders:参与签名计算的头部信息,content-type 和 host 为必选头部。 Signature:签名摘要,计算过程详见下文。 |
| X-TC-Token | String | 否 | 临时证书所用的 Token ,需要结合临时密钥一起使用。临时密钥和 Token 需要到访问管理服务调用接口获取。长期密钥不需要 Token。 |
八、签名方法 V1 公共参数
使用签名方法 v1(有时会称作 HmacSHA256 和 HmacSHA1),公共参数需要统一放到请求串中。
| 参数名称 | 类型 | 必选 | 描述 |
| Action | String | 是 | 操作的接口名称。取值参考接口文档中输入参数公共参数 Action 的说明。例如云服务器的查询实例列表接口,取值为 DescribeInstances。 |
| Region | String | – | 地域参数,用来标识希望操作哪个地域的数据。接口接受的地域取值参考接口文档中输入参数公共参数 Region 的说明。注意:某些接口不需要传递该参数,接口文档中会对此特别说明,此时即使传递该参数也不会生效。 |
| Timestamp | Integer | 是 | 当前 UNIX 时间戳,可记录发起 API 请求的时间。例如1529223702,如果与当前时间相差过大,会引起签名过期错误。 |
| Nonce | Integer | 是 | 随机正整数,与 Timestamp 联合起来,用于防止重放攻击。 |
| SecretId | String | 是 | 在 云API密钥 上申请的标识身份的 SecretId,一个 SecretId 对应唯一的 SecretKey,而 SecretKey 会用来生成请求签名 Signature。 |
| Signature | String | 是 | 请求签名,用来验证此次请求的合法性,需要用户根据实际的输入参数计算得出。具体计算方法参见下文 “签名方法介绍” 。 |
| Version | String | 是 | 操作的 API 的版本。取值参考接口文档中入参公共参数 Version 的说明。例如云服务器的版本2017-03-12。 |
| SignatureMethod | String | 否 | 签名方式,目前支持 HmacSHA256和 HmacSHA1。只有指定此参数为 HmacSHA256时,才使用 HmacSHA256算法验证签名,其他情况均使用 HmacSHA1验证签名。 |
| Token | String | 否 | 临时证书所用的 Token ,需要结合临时密钥一起使用。临时密钥和 Token 需要到访问管理服务调用接口获取。长期密钥不需要 Token 。 |
九、地域列表
由于各个产品支持地域不同,具体详情请参考各产品文档中的地域列表。
例如,你可以参考云服务器的 地域列表。
十、.NET API 调用方式
腾讯云 API 会对每个请求进行身份验证,用户需要使用安全凭证,经过特定的步骤对请求进行签名(Signature),每个请求都需要在公共请求参数中指定该签名结果并以指定的方式和格式发送请求。
假设用户的 SecretId 和 SecretKey 分别是:AKIDz8krbsJ5**********mLPx3EXAMPLE 和 Gu5t9xGAR***********EXAMPLE。用户想查看广州区云服务器名为“未命名”的主机状态,只返回一条数据。则请求可能为:
curl -X POST https://cvm.tencentcloudapi.com \\-H "Authorization: TC3-HMAC-SHA256 Credential=AKIDz8krbsJ5**********mLPx3EXAMPLE/2019-02-25/cvm/tc3_request, SignedHeaders=content-type;host, Signature=72e494ea8******************************************a96525168" \\-H "Content-Type: application/json; charset=utf-8" \\-H "Host: cvm.tencentcloudapi.com" \\-H "X-TC-Action: DescribeInstances" \\-H "X-TC-Timestamp: 1551113065" \\-H "X-TC-Version: 2017-03-12" \\-H "X-TC-Region: ap-guangzhou" \\-d '{"Limit": 1, "Filters": [{"Values": ["\\u672a\\u547d\\u540d"], "Name": "instance-name"}]}'
十一、步骤1:申请安全凭证
这篇使用的安全凭证为密钥,密钥包括 SecretId 和 SecretKey。每个用户最多可以拥有两对密钥。
·SecretId:用于标识 API 调用者身份,可以简单类比为用户名。
·SecretKey:用于验证 API 调用者的身份,可以简单类比为密码。
注意:用户必须严格保管安全凭证,避免泄露,否则将危及财产安全。如已泄露,请立刻禁用该安全凭证。
前往 API 密钥管理 页面,即可进行获取。如下:
注意:为降低密钥泄露的风险,自2023年11月30日起,对所有主账号、子账号的密钥,关闭查询 SecretKey 的功能,仅支持在创建时查看,请及时保存 SecretKey。
十三、1. 获取 API 3.0 V3 版本签名
签名方法 v3(TC3-HMAC-SHA256)功能上覆盖了以前的签名方法 v1,而且更安全,支持更大的请求,支持 json 格式,性能有一定提升,推荐使用该签名方法计算签名。如下:
注意:首次接触,建议使用 API Explorer 中的“签名串生成”功能,选择签名版本为“API 3.0签名 v3”,可以生成签名过程进行验证,也可直接生成 SDK 代码。推荐使用腾讯云 API 配套的7种常见的编程语言 SDK,已经封装了签名和请求过程,均已开源,支持 Python、Java、PHP、Go、NodeJS、.NET、C++。
云 API 支持 GET 和 POST 请求。
·对于GET方法,只支持 Content-Type: application/x-www-form-urlencoded 协议格式。
·对于POST方法,目前支持 Content-Type: application/json 以及 Content-Type: multipart/form-data 两种协议格式,json 格式绝大多数接口均支持,multipart 格式只有特定接口支持,此时该接口不能使用 json 格式调用,参考具体业务接口文档说明。推荐使用 POST 请求,因为两者的结果并无差异,但 GET 请求只支持32KB 以内的请求包。
下面以 查看实例列表 接口为例,分步骤介绍签名的计算过程。我们选择该接口是因为:
1. 云服务器默认已开通,该接口很常用;
2. 该接口是只读的,不会改变现有资源的状态;
3. 接口覆盖的参数种类较全,可以演示包含数据结构的数组如何使用。
十四、1. 拼接规范请求串
CanonicalRequest = HTTPRequestMethod + '\\n' + CanonicalURI + '\\n' + CanonicalQueryString + '\\n' + CanonicalHeaders + '\\n' + SignedHeaders + '\\n' + HashedRequestPayload
| 字段名称 | 解释 |
| HTTPRequestMethod | HTTP 请求方法(GET、POST )。此示例取值为 POST。 |
| CanonicalURI | URI 参数,API 3.0 固定为正斜杠(/)。 |
| CanonicalQueryString | 发起 HTTP 请求 URL 中的查询字符串,对于 POST 请求,固定为空字符串"",对于 GET 请求,则为 URL 中问号(?)后面的字符串内容,例如:Limit=10&Offset=0。 注意:CanonicalQueryString 需要参考 RFC3986 进行 URLEncode,字符集 UTF8,推荐使用编程语言标准库,所有特殊字符均需编码,大写形式。 |
| CanonicalHeaders | 参与签名的头部信息,至少包含 host 和 content-type 两个头部,也可加入自定义的头部参与签名以提高自身请求的唯一性和安全性。 拼接规则:头部 key 和 value 统一转成小写,并去掉首尾空格,按照 key:value\\n 格式拼接;多个头部,按照头部 key(小写)的 ASCII 升序进行拼接。此示例计算结果是 content-type:application/json; charset=utf-8\\nhost:cvm.tencentcloudapi.com\\n。 注意:content-type 必须和实际发送的相符合,有些编程语言网络库即使未指定也会自动添加 charset 值,如果签名时和发送时不一致,服务器会返回签名校验失败。 |
| SignedHeaders | 参与签名的头部信息,说明此次请求有哪些头部参与了签名,和 CanonicalHeaders 包含的头部内容是一一对应的。content-type 和 host 为必选头部。 拼接规则:头部 key 统一转成小写;多个头部 key(小写)按照 ASCII 升序进行拼接,并且以分号(;)分隔。此示例为 content-type;host |
| HashedRequestPayload | 请求正文(Requestpayload,即 body,此示例为 {"Limit": 1, "Filters": [{"Values": ["\\u672a\\u547d\\u540d"], "Name": "instance-name"}]})的哈希值,计算伪代码为 Lowercase(HexEncode(Hash.SHA256(RequestPayload))),即对 HTTP 请求正文做 SHA256 哈希,然后十六进制编码,最后编码串转换成小写字母。对于 GET 请求,RequestPayload 固定为空字符串。此示例计算结果是 35e9c5b0e3ae67532d3c9f17ead6c90222632e5b1ff7f6e89887f1398934f064。 |
根据以上规则,示例中得到的规范请求串如下:
POST/content-type:application/json; charset=utf-8host:cvm.tencentcloudapi.comcontent-type;host35e9c5b0e3ae67532d3c9f17ead6c90222632e5b1ff7f6e89887f1398934f064
十五、2. 拼接待签名字符串
按如下格式拼接待签名字符串:
StringToSign = Algorithm + \\n + RequestTimestamp + \\n + CredentialScope + \\n + HashedCanonicalRequest
| 字段名称 | 解释 |
| Algorithm | 签名算法,目前固定为 TC3-HMAC-SHA256。 |
| RequestTimestamp | 请求时间戳,即请求头部的公共参数 X-TC-Timestamp 取值,取当前时间 UNIX 时间戳,精确到秒。此示例取值为 1551113065。 |
| CredentialScope | 凭证范围,格式为 Date/service/tc3_request,包含日期、所请求的服务和终止字符串(tc3_request)。Date 为 UTC 标准时间的日期,取值需要和公共参数 X-TC-Timestamp 换算的 UTC 标准时间日期一致;service 为产品名,必须与调用的产品域名一致。此示例计算结果是 2019-02-25/cvm/tc3_request。 |
| HashedCanonicalRequest | 前述步骤拼接所得规范请求串的哈希值,计算伪代码为 Lowercase(HexEncode(Hash.SHA256(CanonicalRequest)))。此示例计算结果是 5ffe6a04c0664d6b969fab9a13bdab201d63ee709638e2749d62a09ca18d7031。 |
根据以上规则,示例中得到的待签名字符串如下:
TC3-HMAC-SHA25615511130652019-02-25/cvm/tc3_request5ffe6a04c0664d6b969fab9a13bdab201d63ee709638e2749d62a09ca18d7031
十六、3.计算签名(伪代码)
实际请参考下面示例:
byte[] tc3SecretKey = Encoding.UTF8.GetBytes("TC3" + SECRET_KEY);byte[] secretDate = HmacSHA256(tc3SecretKey, Encoding.UTF8.GetBytes(date));byte[] secretService = HmacSHA256(secretDate, Encoding.UTF8.GetBytes(service));byte[] secretSigning = HmacSHA256(secretService, Encoding.UTF8.GetBytes("tc3_request"));byte[] signatureBytes = HmacSHA256(secretSigning, Encoding.UTF8.GetBytes(stringToSign));string signature = BitConverter.ToString(signatureBytes).Replace("-", "").ToLower();
此示例计算结果是 72e494ea8******************************************a96525168。
十七、4. 拼接 Authorization
按如下格式拼接 Authorization:
Authorization = Algorithm + ' ' + 'Credential=' + SecretId + '/' + CredentialScope + ', ' + 'SignedHeaders=' + SignedHeaders + ', ' + 'Signature=' + Signature
| 字段名称 | 解释 |
| Algorithm | 签名方法,固定为 TC3-HMAC-SHA256。 |
| SecretId | 密钥对中的 SecretId,即 AKIDz8krbsJ5**********mLPx3EXAMPLE。 |
| CredentialScope | 见上文,凭证范围。此示例计算结果是 2019-02-25/cvm/tc3_request。 |
| SignedHeaders | 见上文,参与签名的头部信息。此示例取值为 content-type;host。 |
| Signature | 签名值。此示例计算结果是 72e494ea8******************************************a96525168。 |
根据以上规则,示例中得到的值为:
TC3-HMAC-SHA256 Credential=AKIDz8krbsJ5**********mLPx3EXAMPLE/2019-02-25/cvm/tc3_request, SignedHeaders=content-type;host, Signature=72e494ea8******************************************a96525168
最终完整的调用信息如下:
POST https://cvm.tencentcloudapi.com/Authorization: TC3-HMAC-SHA256 Credential=AKIDz8krbsJ5**********mLPx3EXAMPLE/2019-02-25/cvm/tc3_request, SignedHeaders=content-type;host, Signature=72e494ea8******************************************a96525168Content-Type: application/json; charset=utf-8Host: cvm.tencentcloudapi.comX-TC-Action: DescribeInstancesX-TC-Version: 2017-03-12X-TC-Timestamp: 1551113065X-TC-Region: ap-guangzhou{"Limit": 1, "Filters": [{"Values": ["\\u672a\\u547d\\u540d"], "Name": "instance-name"}]}
十八、5. API 3.0签名 V3示例
using System;using System.Collections.Generic;using System.Security.Cryptography;using System.Text;public class Application { public static string SHA256Hex(string s) { using (SHA256 algo = SHA256.Create()) { byte[] hashbytes = algo.ComputeHash(Encoding.UTF8.GetBytes(s)); StringBuilder builder = new StringBuilder(); for (int i = 0; i < hashbytes.Length; ++i) { builder.Append(hashbytes[i].ToString("x2")); } return builder.ToString(); } } public static byte[] HmacSHA256(byte[] key, byte[] msg) { using (HMACSHA256 mac = new HMACSHA256(key)) { return mac.ComputeHash(msg); } } public static void Main(string[] args) { // 密钥参数 // 需要设置环境变量 TENCENTCLOUD_SECRET_ID,值为示例的 AKIDz8krbsJ5**********mLPx3EXAMPLE string SECRET_ID = Environment.GetEnvironmentVariable("TENCENTCLOUD_SECRET_ID"); // 需要设置环境变量 TENCENTCLOUD_SECRET_KEY,值为示例的 Gu5t9xGAR***********EXAMPLE string SECRET_KEY = Environment.GetEnvironmentVariable("TENCENTCLOUD_SECRET_KEY"); string service = "cvm"; string endpoint = "cvm.tencentcloudapi.com"; string region = "ap-guangzhou"; string action = "DescribeInstances"; string version = "2017-03-12"; string algorithm = "TC3-HMAC-SHA256"; string contentType = "application/json"; double RequestTimestamp = 1551113065; // 时间戳 2019-02-26 00:44:25,此参数作为示例,以实际为准 // long timestamp = ToTimestamp() / 1000; // string requestTimestamp = timestamp.ToString(); string date = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(RequestTimestamp).ToString("yyyy-MM-dd"); // 注意时区,否则容易出错 // ************* 步骤 1:拼接规范请求串 ************* string httpRequestMethod = "POST"; string canonicalUri = "/"; string canonicalQueryString = ""; string canonicalHeaders = "content-type:" + contentType +"; charset=utf-8\\n" + "host:" + endpoint + "\\n"; string signedHeaders = "content-type;host"; string requestPayload = "{\\"Limit\\": 1, \\"Filters\\": [{\\"Values\\": [\\"\\\\u672a\\\\u547d\\\\u540d\\"], \\"Name\\": \\"instance-name\\"}]}"; string hashedRequestPayload = SHA256Hex(requestPayload); string canonicalRequest = httpRequestMethod + "\\n" + canonicalUri + "\\n" + canonicalQueryString + "\\n" + canonicalHeaders + "\\n" + signedHeaders + "\\n" + hashedRequestPayload; Console.WriteLine(canonicalRequest); Console.WriteLine("———————————-"); // ************* 步骤 2:拼接待签名字符串 ************* string credentialScope = date + "/" + service + "/" + "tc3_request"; string hashedCanonicalRequest = SHA256Hex(canonicalRequest); string stringToSign = algorithm + "\\n" + RequestTimestamp + "\\n" + credentialScope + "\\n" + hashedCanonicalRequest; Console.WriteLine(stringToSign); Console.WriteLine("———————————-"); // ************* 步骤 3:计算签名 ************* byte[] tc3SecretKey = Encoding.UTF8.GetBytes("TC3" + SECRET_KEY); byte[] secretDate = HmacSHA256(tc3SecretKey, Encoding.UTF8.GetBytes(date)); byte[] secretService = HmacSHA256(secretDate, Encoding.UTF8.GetBytes(service)); byte[] secretSigning = HmacSHA256(secretService, Encoding.UTF8.GetBytes("tc3_request")); byte[] signatureBytes = HmacSHA256(secretSigning, Encoding.UTF8.GetBytes(stringToSign)); string signature = BitConverter.ToString(signatureBytes).Replace("-", "").ToLower(); Console.WriteLine(signature); Console.WriteLine("———————————-"); // ************* 步骤 4:拼接 Authorization ************* string authorization = algorithm + " " + "Credential=" + SECRET_ID + "/" + credentialScope + ", " + "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature; Console.WriteLine(authorization); Console.WriteLine("———————————-"); Dictionary<string, string> headers = new Dictionary<string, string>(); headers.Add("Authorization", authorization); headers.Add("Host", endpoint); headers.Add("Content-Type", contentType + "; charset=utf-8"); headers.Add("X-TC-Timestamp", RequestTimestamp.ToString()); headers.Add("X-TC-Version", version); headers.Add("X-TC-Action", action); headers.Add("X-TC-Region", region); Console.WriteLine("POST https://cvm.tencentcloudapi.com"); foreach (KeyValuePair<string, string> kv in headers) { Console.WriteLine(kv.Key + ": " + kv.Value); } Console.WriteLine(); Console.WriteLine(requestPayload); }}
十九、2. 获取 API 3.0 V1 版本签名
签名方法 v1(HmacSHA1、HmacSHA256)简单易用,但是功能和安全性都不如签名方法 v3,推荐使用签名方法 v3。
首次接触,建议使用 API Explorer 中的“签名串生成”功能,选择签名版本为“API 3.0签名 v1”,可以生成签名过程进行验证,并提供了部分编程语言的签名示例,也可直接生成 SDK 代码。推荐使用腾讯云 API 配套的 7 种常见的编程语言 SDK,已经封装了签名和请求过程,均已开源,支持 Python、Java、PHP、Go、NodeJS、.NET、C++。
以云服务器查看实例列表(DescribeInstances)请求为例,当用户调用这一接口时,其请求参数可能如下:
| 参数名称 | 中文 | 参数值 |
| Action | 方法名 | DescribeInstances |
| SecretId | 密钥 ID | AKIDz8krbsJ5**********mLPx3EXAMPLE |
| Timestamp | 当前时间戳 | 1465185768 |
| Nonce | 随机正整数 | 11886 |
| Region | 实例所在区域 | ap-guangzhou |
| InstanceIds.0 | 待查询的实例 ID | ins-09dx96dg |
| Offset | 偏移量 | 0 |
| Limit | 最大允许输出 | 20 |
| Version | 接口版本号 | 2017-03-12 |
20、1. 对参数排序
首先对所有请求参数按参数名的字典序(ASCII 码)升序排序。
上述示例参数的排序结果如下:
{ 'Action' : 'DescribeInstances', 'InstanceIds.0' : 'ins-09dx96dg', 'Limit' : 20, 'Nonce' : 11886, 'Offset' : 0, 'Region' : 'ap-guangzhou', 'SecretId' : 'AKIDz8krbsJ5**********mLPx3EXAMPLE', 'Timestamp' : 1465185768, 'Version': '2017-03-12',}
使用程序设计语言开发时,可对上面示例中的参数进行排序,得到的结果一致即可。
21、2. 拼接规范请求串
此步骤生成请求字符串。 将把上一步排序好的请求参数格式化成“参数名称=参数值”的形式,如对 Action 参数,其参数名称为 "Action",参数值为 "DescribeInstances",因此格式化后就为 Action=DescribeInstances。
注意:“参数值”为原始值而非 url 编码后的值。
然后将格式化后的各个参数用"&"拼接在一起,最终生成的请求字符串为:
Action=DescribeInstances&InstanceIds.0=ins-09dx96dg&Limit=20&Nonce=11886&Offset=0&Region=ap-guangzhou&SecretId=AKIDz8krbsJ5**********mLPx3EXAMPLE&Timestamp=1465185768&Version=2017-03-12
22、3. 拼接待签名字符串
此步骤生成签名原文字符串。 签名原文字符串由以下几个参数构成:
1. 请求方法:支持 POST 和 GET 方式,这里使用 GET 请求,注意方法为全大写。
2. 请求主机:查看实例列表(DescribeInstances)的请求域名为:cvm.tencentcloudapi.com。实际的请求域名根据接口所属模块的不同而不同,详见各接口说明。
3. 请求路径:当前版本云 API 的请求路径固定为 / 。
4. 请求字符串:即上一步生成的请求字符串。
签名原文串的拼接规则为:请求方法 + 请求主机 +请求路径 + ? + 请求字符串 。
示例的拼接结果为:
GETcvm.tencentcloudapi.com/?Action=DescribeInstances&InstanceIds.0=ins-09dx96dg&Limit=20&Nonce=11886&Offset=0&Region=ap-guangzhou&SecretId=AKIDz8krbsJ5**********mLPx3EXAMPLE&Timestamp=1465185768&Version=2017-03-12
23、4. 计算签名(伪代码)
此步骤生成签名串。 首先使用 HMAC-SHA1 算法对上一步中获得的签名原文字符串进行签名,然后将生成的签名串使用 Base64进行编码,即可获得最终的签名串。
public static string Sign(string signKey, string secret, string SignatureMethod) { string signRet = string.Empty; using (HMACSHA1 mac = new HMACSHA1(Encoding.UTF8.GetBytes(signKey))) { byte[] hash = mac.ComputeHash(Encoding.UTF8.GetBytes(secret)); signRet = Convert.ToBase64String(hash); } return signRet; }
24、5. 获取调用信息并发送请求
# 实际调用,成功后可能如果是消费接口会产生计费(此处以Python语言为例发送get请求)resp = requests.get("https://" + endpoint, params=data)print(resp.url)
最终得到的请求串为:
https://cvm.tencentcloudapi.com/?Action=DescribeInstances&InstanceIds.0=ins-09dx96dg&Limit=20&Nonce=11886&Offset=0&Region=ap-guangzhou&SecretId=AKIDz8krbsJ5**********mLPx3EXAMPLE&Signature=EliP9YW3pW28FpsEdkXt%2F%2BWcGeI%3D&Timestamp=1465185768&Version=2017-03-12
| 字段名称 | 解释 |
| endpoint | 服务地址, 例如:cvm.tencentcloudapi.com |
| data | API 3.0签名 V1所举示例接口参数,注意 这里需要将计算的签名以键值对的形式加入 data 中。 |
注意:由于示例中的密钥是虚构的,时间戳也不是系统当前时间,因此如果将此 url 在浏览器中打开或者用 curl 等命令调用时会返回鉴权错误:签名过期。为了得到一个可以正常返回的 url ,需要修改示例中的 SecretId 和 SecretKey 为真实的密钥,并使用系统当前时间戳作为 Timestamp。
为了更清楚的解释签名过程,下面以 .NET 语言为例,将上述的签名过程具体实现。请求的域名、调用的接口和参数的取值都以上述签名过程为准,代码只为解释签名过程,并不具备通用性,实际开发请尽量使用 SDK。
25、6. 签名串编码
生成的签名串并不能直接作为请求参数,需要对其进行 URL 编码。
如上一步生成的签名串为 Eli*****************cGeI=,最终得到的签名串请求参数(Signature)为:EliP***********************eI%3D,它将用于生成最终的请求 URL。
26、7. API 3.0签名 V1示例
using System;using System.Collections.Generic;using System.Net;using System.Security.Cryptography;using System.Text;public class Application { public static string Sign(string signKey, string secret) { string signRet = string.Empty; using (HMACSHA1 mac = new HMACSHA1(Encoding.UTF8.GetBytes(signKey))) { byte[] hash = mac.ComputeHash(Encoding.UTF8.GetBytes(secret)); signRet = Convert.ToBase64String(hash); } return signRet; } public static string MakeSignPlainText(SortedDictionary<string, string> requestParams, string requestMethod, string requestHost, string requestPath) { string retStr = ""; retStr += requestMethod; retStr += requestHost; retStr += requestPath; retStr += "?"; string v = ""; foreach (string key in requestParams.Keys) { v += string.Format("{0}={1}&", key, requestParams[key]); } retStr += v.TrimEnd('&'); return retStr; } public static void Main(string[] args) { // 密钥参数 // 需要设置环境变量 TENCENTCLOUD_SECRET_ID,值为示例的 AKIDz8krbsJ5**********mLPx3EXAMPLE string SECRET_ID = Environment.GetEnvironmentVariable("TENCENTCLOUD_SECRET_ID"); // 需要设置环境变量 TENCENTCLOUD_SECRET_KEY,值为示例的 Gu5t9xGAR***********EXAMPLE string SECRET_KEY = Environment.GetEnvironmentVariable("TENCENTCLOUD_SECRET_KEY"); string endpoint = "cvm.tencentcloudapi.com"; string region = "ap-guangzhou"; string action = "DescribeInstances"; string version = "2017-03-12"; double RequestTimestamp = 1465185768; // 时间戳 2019-02-26 00:44:25,此参数作为示例,以实际为准 // long timestamp = ToTimestamp() / 1000; // string requestTimestamp = timestamp.ToString(); Dictionary<string, string> param = new Dictionary<string, string>(); param.Add("Limit", "20"); param.Add("Offset", "0"); param.Add("InstanceIds.0", "ins-09dx96dg"); param.Add("Action", action); param.Add("Nonce", "11886"); // param.Add("Nonce", Math.Abs(new Random().Next()).ToString()); param.Add("Timestamp", RequestTimestamp.ToString()); param.Add("Version", version); param.Add("SecretId", SECRET_ID); param.Add("Region", region); SortedDictionary<string, string> headers = new SortedDictionary<string, string>(param, StringComparer.Ordinal); string sigInParam = MakeSignPlainText(headers, "GET", endpoint, "/"); Console.WriteLine(sigInParam); string sigOutParam = Sign(SECRET_KEY, sigInParam); Console.WriteLine("GET https://cvm.tencentcloudapi.com"); foreach (KeyValuePair<string, string> kv in headers) { Console.WriteLine(kv.Key + ": " + kv.Value); } Console.WriteLine("Signature" + ": " + WebUtility.UrlEncode(sigOutParam)); Console.WriteLine(); string result = "https://cvm.tencentcloudapi.com/?"; foreach (KeyValuePair<string, string> kv in headers) { result += WebUtility.UrlEncode(kv.Key) + "=" + WebUtility.UrlEncode(kv.Value) + "&"; } result += WebUtility.UrlEncode("Signature") + "=" + WebUtility.UrlEncode(sigOutParam); Console.WriteLine("GET " + result); }}
27、API 2.0签名
此签名现已不在维护,建议使用性能更优的 API 3.0签名 ,如需使用,请直接在 API Explorer 的 签名串生成 > 选择 API 2.0签名 版本进行操作。
28、签名失败
存在以下签名失败的错误码,请根据实际情况处理。
| 错误码 | 错误描述 |
| AuthFailure.SignatureExpire | 签名过期。Timestamp 与服务器接收到请求的时间相差不得超过五分钟。 |
| AuthFailure.SecretIdNotFound | 密钥不存在。请到控制台查看密钥是否被禁用,是否少复制了字符或者多了字符。 |
| AuthFailure.SignatureFailure | 签名错误。可能是签名计算错误,或者签名与实际发送的内容不相符合,也有可能是密钥 SecretKey 错误导致的。 |
| AuthFailure.TokenFailure | 临时证书 Token 错误。 |
| AuthFailure.InvalidSecretId | 密钥非法(不是云 API 密钥类型)。 |
30、正确返回结果
以云服务器的接口查看实例状态列表(DescribeInstancesStatus)2017-03-12版本为例,若调用成功,其可能的返回如下为:
{ "Response": { "TotalCount": 0, "InstanceStatusSet": [], "RequestId": "b5b41468-520d-4192-b42f-595cc34b6c1c" }}
·Response 及其内部的 RequestId 是固定的字段,无论请求成功与否,只要 API 处理了,则必定会返回。
·RequestId 用于一个 API 请求的唯一标识,如果 API 出现异常,可以联系我们,并提供该 ID 来解决问题。
·除了固定的字段外,其余均为具体接口定义的字段,不同的接口所返回的字段参见接口文档中的定义。此例中的 TotalCount 和 InstanceStatusSet 均为 DescribeInstancesStatus 接口定义的字段,由于调用请求的用户暂时还没有云服务器实例,因此 TotalCount 在此情况下的返回值为 0, InstanceStatusSet 列表为空。
31、错误返回结果
若调用失败,其返回值示例如下为:
{ "Response": { "Error": { "Code": "AuthFailure.SignatureFailure", "Message": "The provided credentials could not be validated. Please check your signature is correct." }, "RequestId": "ed93f3cb-f35e-473f-b9f3-0d451b8b79c6" }}
·Error 的出现代表着该请求调用失败。Error 字段连同其内部的 Code 和 Message 字段在调用失败时是必定返回的。
·Code 表示具体出错的错误码,当请求出错时可以先根据该错误码在公共错误码和当前接口对应的错误码列表里面查找对应原因和解决方案。
·Message 显示出了这个错误发生的具体原因,随着业务发展或体验优化,此文本可能会经常保持变更或更新,用户不应依赖这个返回值。
·RequestId 用于一个 API 请求的唯一标识,如果 API 出现异常,可以联系我们,并提供该 ID 来解决问题。
32、公共错误码
返回结果中如果存在 Error 字段,则表示调用 API 接口失败。 Error 中的 Code 字段表示错误码,所有业务都可能出现的错误码为公共错误码,下表列出了公共错误码。
| 错误码 | 错误描述 |
| AuthFailure.InvalidSecretId | 密钥非法(不是云 API 密钥类型)。 |
| AuthFailure.MFAFailure | MFA 错误。 |
| AuthFailure.SecretIdNotFound | 密钥不存在。 |
| AuthFailure.SignatureExpire | 签名过期。 |
| AuthFailure.SignatureFailure | 签名错误。 |
| AuthFailure.TokenFailure | token 错误。 |
| AuthFailure.UnauthorizedOperation | 请求未 CAM 授权。 |
| DryRunOperation | DryRun 操作,代表请求将会是成功的,只是多传了 DryRun 参数。 |
| FailedOperation | 操作失败。 |
| InternalError | 内部错误。 |
| InvalidAction | 接口不存在。 |
| InvalidParameter | 参数错误。 |
| InvalidParameterValue | 参数取值错误。 |
| LimitExceeded | 超过配额限制。 |
| MissingParameter | 缺少参数错误。 |
| NoSuchVersion | 接口版本不存在。 |
| RequestLimitExceeded | 请求的次数超过了频率限制。 |
| ResourceInUse | 资源被占用。 |
| ResourceInsufficient | 资源不足。 |
| ResourceNotFound | 资源不存在。 |
| ResourceUnavailable | 资源不可用。 |
| UnauthorizedOperation | 未授权操作。 |
| UnknownParameter | 未知参数错误。 |
| UnsupportedOperation | 操作不支持。 |
| UnsupportedProtocol | HTTPS 请求方法错误,只支持 GET 和 POST 请求。 |
| UnsupportedRegion | 接口不支持所传地域。 |