签名方法

最近更新时间:2024-11-04 10:38:48

腾讯云 API 会对每个访问的请求进行身份验证,即每个请求都需要在公共请求参数中包含签名信息(Signature),以验证用户身份。签名信息由用户所持有的安全凭证生成,安全凭证包括 SecretId 和 SecretKey,若用户还没有安全凭证,则需要在腾讯云官网上自主申请,否则无法调用云 API 接口。

申请安全凭证

在第一次使用腾讯云 API 之前,用户需要在【腾讯云控制台】> 【API 密钥管理 】上申请安全凭证。安全凭证包括 SecretId 和 SecretKey,其中:

  • SecretId:用于标识 API 调用者身份。
  • SecretKey:用于加密签名字符串和服务器端验证签名字符串的密钥。
注意:

API 密钥是构建腾讯云 API 请求的重要凭证,使用腾讯云 API 可以操作您名下的所有腾讯云资源,为了您的财产和服务安全,请妥善保存并定期更换密钥,当您更换密钥后,请及时删除旧密钥。

申请安全凭证步骤:

  1. 登录 腾讯云控制台
  2. 单击【云产品】,选择【管理与审计】栏下的【访问密钥】,进入访问密钥管理页面。
  3. API 密钥管理 页面,单击【新建密钥】即可以创建一对 SecretId/SecretKey。
注意:

  • 开发商账号最多可以拥有两对 SecretId / SecretKey。
  • 被开发商添加为子用户的 QQ 账号,在不同开发商控制台,可以申请不同的安全凭证。
  • 子用户的安全凭证,目前仅可调用部分接口的云 API。

生成签名串

有了安全凭证 SecretId 和 SecretKey 后,就可以生成签名串了。生成签名串的详细过程如下:

以腾讯云 CVM 为例,当用户调用腾讯云 CVM 的 查看实例列表 (DescribeInstances)接口时,其请求参数为:

参数名称 描述 参数值
Action 方法名 DescribeInstances
SecretId 密钥 ID ****
Timestamp 当前时间戳 1465185768
Nonce 随机正整数 11886
Region 实例所在区域 ap-guangzhou
SignatureMethod 签名方式 HmacSHA256
InstanceIds.0 待查询的实例 ID ins-09dx96dg

1. 对参数排序

首先对所有请求参数按参数名做字典序升序排列。(所谓字典序升序排列,直观上就如同在字典中排列单词一样排序,按照字母表或数字表里递增顺序的排列次序,即先考虑第一个“字母”,在相同的情况下考虑第二个“字母”,依此类推。)您可以借助编程语言中的相关排序函数来实现这一功能,如 PHP 中的 ksort 函数。上述示例参数的排序结果如下:

{
    "Action" : "DescribeInstances",
    "InstanceIds.0" : "ins-09dx96dg",
    "Nonce" : "11886",
    "Region" : "ap-guangzhou",
    "SecretId" : "************************************",
    "SignatureMethod" : "HmacSHA256",
    "Timestamp" : "1465185768"
}
使用其它程序设计语言开发时, 可对上面示例中的参数进行排序,得到的结果一致即可。

2. 拼接请求字符串

此步骤将生成请求字符串。
将把上一步排序好的请求参数格式化成“参数名称”=“参数值”的形式,如对 Action 参数,其参数名称为"Action",参数值为"DescribeInstances",因此格式化后就为 Action=DescribeInstances

注意:

  • “参数值”为原始值而非 URL 编码后的值。
  • 若输入参数的 Key 中包含下划线,则需要将其转换为.,但是 Value 中的下划线则不用转换。如Placement_Zone=CN_GUANGZHOU, 则需要将其转换成Placement.Zone=CN_GUANGZHOU

然后将格式化后的各个参数用"&"拼接在一起,最终生成的请求字符串为(请忽略文中的换行):

Action=DescribeInstances
&InstanceIds.0=ins-09dx96dg
&Nonce=11886
&Region=ap-guangzhou
&SecretId=************************************
&SignatureMethod=HmacSHA256
&Timestamp=1465185768

3. 拼接签名原文字符串

此步骤将生成签名原文字符串。
签名原文字符串的拼接规则为:

请求方法 + 请求主机 +请求路径 + ? + 请求字符串

参数构成说明:

  • 请求方法: 支持 POST 和 GET 方式,这里使用 GET 请求, 注意方法为全大写。
  • 请求主机:即主机域名,请求域名由接口所属的产品或所属产品的模块决定,不同产品或不同产品的模块的请求域名会有不同。如腾讯云 CVM 的查询实例列表(DescribeInstances)的请求域名为:cvm.api.qcloud.com,具体产品请求域名详见各接口说明。
  • 请求路径: 腾讯云 API 对应产品的请求路径,一般是一个产品对应一个固定路径,如腾讯云 CVM 请求路径固定为/v2/index.php
  • 请求字符串: 即上一步生成的请求字符串。

因此,上述示例的拼接签名原文字符串结果为(请忽略文中的换行):

GETcvm.api.qcloud.com/v2/index.php?Action=DescribeInstances
&InstanceIds.0=ins-09dx96dg
&Nonce=11886
&Region=ap-guangzhou
&SecretId=************************************
&SignatureMethod=HmacSHA256
&Timestamp=1465185768

4. 生成签名串

此步骤生成签名串。

注意:

计算签名的方法有两种:HmacSHA256 和 HmacSHA1 这里要根据您指定的签名算法(即 SignatureMethod 参数)生成签名串。当指定 SignatureMethod 为 HmacSHA256 时,需要使用 HmacSHA256 计算签名,其他情况请使用 HmacSHA1 计算签名。

首先使用签名算法(HmacSHA256 或 HmacSHA1)对上一步中获得的 签名原文字符串 进行签名,然后将生成的签名串使用 Base64 进行编码,即可获得最终的签名串。

具体代码如下,以 PHP 语言为例,由于本例中所用的签名算法为 HmacSHA256,因此生成签名串的代码如下(使用其它程序设计语言开发时,可用上述示例中的原文字符串进行签名验证,得到的签名串与例子中的一致即可):

$secretKey = '********************************';
$srcStr = 'GETcvm.api.qcloud.com/v2/index.php?Action=DescribeInstances&InstanceIds.0=ins-09dx96dg&Nonce=11886&Region=ap-guangzhou&SecretId=************************************&SignatureMethod=HmacSHA256&Timestamp=1465185768';
$signStr = base64_encode(hash_hmac('sha256', $srcStr, $secretKey, true));
echo $signStr;

最终得到的签名串为:

0EEm/HtGRr/********************************=

同理,当您指定签名算法为 HmacSHA1 时,生成签名串的代码如下:

$secretKey = '********************************';
$srcStr = 'GETcvm.api.qcloud.com/v2/index.php?Action=DescribeInstances&InstanceIds.0=ins-09dx96dg&Nonce=11886&Region=ap-guangzhou&SecretId=************************************&SignatureMethod=HmacSHA1&Timestamp=1465185768';
$signStr = base64_encode(hash_hmac('sha1', $srcStr, $secretKey, true));
echo $signStr;

最终得到的签名串为:

nPVnY6njQmwQ8ciqbPl5Qe+Oru4=

签名串编码

生成的签名串并不能直接作为请求参数,需要对其进行 URL 编码。
如上一步生成的签名串为0EEm/HtGRr/********************************=,则其编码后为0EEm%2FHtGRr%2********************************%3D。因此,最终得到的签名串请求参数 (Signature) 为:0EEm%2FHtGRr%2********************************%3D,它将用于生成最终的请求URL。

注意:

如果用户的请求方法是 GET,则对所有请求参数的参数值均需要做 URL 编码;此外,部分语言库会自动对 URL 进行编码,重复编码会导致签名校验失败。

鉴权失败

当鉴权不通过时,可能出现如下表的错误:

错误代码 错误类型 错误描述
4100 身份认证失败 身份验证失败,请确保您请求参数中的 Signature 按照上述步骤计算正确,特别注意 Signature 要做 url 编码后再发起请求。
4101 未被开发商授权访问本接口 该子用户未被授权调用此接口。请联系开发商授权,详情请查阅 授权策略
4102 未被开发商授权访问本接口中所操作的资源 请求的资源参数中,存在未被开发商授权访问的资源,请在 message 字段中查看无权查看的资源 ID。
请联系开发商授权,详情请查阅 授权策略
4103 非开发商的 SecretId 暂不支持调用本接口 子用户的 SecretId 不支持调用此接口,只有开发商有权调用。
4104 SecretId 不存在 签名所用的 SecretId 不存在,也可能是密钥状态有误,请确保 API 密钥有效且未被禁用。
4110 鉴权失败 权限校验失败,请确保您有使用所访问资源的权限。
4500 重放攻击错误 请注意 Nonce 参数两次请求不能重复,Timestamp 与腾讯服务器相差不能超过2小时。