签名方法

最近更新时间:2018-07-27 15:42:27

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

1. 申请安全凭证

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

SecretId:用于标识 API 调用者身份;

SecretKey:用于加密签名字符串和服务器端验证签名字符串的密钥。

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

申请安全凭证的具体步骤如下:

1) 登录腾讯云管理中心控制台

2) 单击【云产品】,选择【监控与管理】栏下的【云API密钥】,进入云API密钥管理页面。

3) 在云API访问密钥管理页面,单击【新建】即可以创建一对SecretId/SecretKey。

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

2. 生成签名串

有了安全凭证SecretId 和 SecretKey后,就可以生成签名串了。下面给出了一个生成签名串的详细过程。

假设用户的 SecretId 和 SecretKey 分别是:

SecretId: AKIDz8krbsJ5yKBZQpn74WFkmLPx3gnPhESA

SecretKey: Gu5t9xGARNpq86cd98joQYCN3Cozk1qA

注意:这里只是示例,请用户根据自己实际的SecretId和SecretKey和请求参数进行后续操作!

查询实例列表(DescribeCdbInstances)请求为例,当用户调用这一接口时,其请求参数可能如下:

参数名称 中文 参数值
Action 方法名 DescribeCdbInstances
SecretId 密钥Id AKIDz8krbsJ5yKBZQpn74WFkmLPx3gnPhESA
Timestamp 当前时间戳 1465185768
Nonce 随机正整数 11886
Region 实例所在区域 ap-guangzhou
SignatureMethod 签名方式 HmacSHA256
cdbInstanceIds.0 待查询的实例ID cdb-09dx96dg

2.1. 对参数排序

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

{
    "Action" : "DescribeCdbInstances",
    "Nonce" : 11886,
    "Region" : "ap-guangzhou",
    "SecretId" : "AKIDz8krbsJ5yKBZQpn74WFkmLPx3gnPhESA",
    "SignatureMethod" : "HmacSHA256",
    "Timestamp" : 1465185768,
    "cdbInstanceIds.0" : "cdb-09dx96dg"
}

使用其它程序设计语言开发时, 可对上面示例中的参数进行排序,得到的结果一致即可。

2.2. 拼接请求字符串

此步骤生成请求字符串。
将把上一步排序好的请求参数格式化成“参数名称”=“参数值”的形式,如对Action参数,其参数名称为"Action",参数值为"DescribeCdbInstances",因此格式化后就为Action=DescribeCdbInstances。
注意:1、“参数值” 为原始值而非url编码后的值。2、若输入参数的Key中包含下划线,则需要将其转换为“.”,但是 Value 中的下划线则不用转换。如 Placement_Zone=CN_GUANGZHOU, 则需要将其转换成Placement.Zone=CN_GUANGZHOU。

然后将格式化后的各个参数用"&"拼接在一起,最终生成的请求字符串为:

Action=DescribeCdbInstances&cdbInstanceIds.0=cdb-09dx96dg&Nonce=11886&Region=ap-guangzhou&SecretId=AKIDz8krbsJ5yKBZQpn74WFkmLPx3gnPhESA&SignatureMethod=HmacSHA256&Timestamp=1465185768

2.3. 拼接签名原文字符串

此步骤生成签名原文字符串。
签名原文字符串由以下几个参数构成:

  • 请求方法: 支持 POST 和 GET 方式, 这里使用 GET 请求, 注意方法为全大写。
  • 请求主机:查询实例列表(DescribeCdbInstances)的请求域名为:cdb.api.qcloud.com。实际的请求域名根据接口所属模块的不同而不同, 详见各接口说明。
  • 请求路径: 云API的请求路径固定为/v2/index.php。
  • 请求字符串: 即上一步生成的请求字符串。

签名原文串的拼接规则为:

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

示例的拼接结果为:

GETcdb.api.qcloud.com/v2/index.php?Action=DescribeCdbInstances&cdbInstanceIds.0=cdb-09dx96dg&Nonce=11886&Region=ap-guangzhou&SecretId=AKIDz8krbsJ5yKBZQpn74WFkmLPx3gnPhESA&SignatureMethod=HmacSHA256&Timestamp=1465185768

2.4. 生成签名串

此步骤生成签名串。

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

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

具体代码如下,以 PHP 语言为例,由于本例中所用的签名算法为HmacSHA256,因此生成签名串的代码如下:

$secretKey = 'Gu5t9xGARNpq86cd98joQYCN3Cozk1qA';
$srcStr = 'GETcdb.api.qcloud.com/v2/index.php?Action=DescribeCdbInstances&cdbInstanceIds.0=cdb-09dx96dg&Nonce=11886&Region=ap-guangzhou&SecretId=AKIDz8krbsJ5yKBZQpn74WFkmLPx3gnPhESA&SignatureMethod=HmacSHA256&Timestamp=1465185768';
$signStr = base64_encode(hash_hmac('sha256', $srcStr, $secretKey, true));
echo $signStr;

最终得到的签名串为:

ngb/op13o8wff5ZpBsK7ZSvH+gKmChu95PgXPG2P5oQ=

同理,当您指定签名算法为HmacSHA1时(即未指定SignatureMethod参数为HmacSHA256),生成签名串的代码如下:

$secretKey = 'Gu5t9xGARNpq86cd98joQYCN3Cozk1qA';
$srcStr = 'GETcdb.api.qcloud.com/v2/index.php?Action=DescribeCdbInstances&cdbInstanceIds.0=ins-09dx96dg&Nonce=11886&Region=ap-guangzhou&SecretId=AKIDz8krbsJ5yKBZQpn74WFkmLPx3gnPhESA&SignatureMethod=HmacSHA256&Timestamp=1465185768';
$signStr = base64_encode(hash_hmac('sha1', $srcStr, $secretKey, true));
echo $signStr;

最终得到的签名串为:

PFKj1Yx9kVKB0nn4Q2G+TlRx09E=

使用其它程序设计语言开发时, 可用上面示例中的原文进行签名验证, 得到的签名串与例子中的一致即可。

3. 签名串编码

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

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

4. 鉴权失败

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

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