2023年7月10日发(作者:)
Python和PHP对腾讯云签名hmac_sha256算法实现开宗明义,⽶扑科技在使⽤腾讯云的API接⼝签名中,按照官⽅⽰例开发PHP、Python的接⼝,经常会提⽰签名错误 1
2
3
4
5
6
7
8
9
"Message":
"The provided credentials could not be validated. Please check your signature is correct."
},
"RequestId":
"1ee6ae98-a971-ad9f-4ecc-abcd69ea1234"
}}
"Code":
"ureFailure","Response": {
"Error": {{
本⽂原⽂,请参见⽶扑博客:经过多次尝试探究,发现原因有⼆:1)腾讯云官⽅⽰例不严谨,没有urlencode() 或 () 编码导致提⽰签名错误2)腾讯官⽅只提供了PHP⽰例,没有提供Python⽰例,两者签名函数有⼀些细节
直接给出⼲货,下⾯⽰例是 封装好的腾讯云签名函数,以飨读者。腾讯云签名:阿⾥云签名:⽶扑的官⽹:
PHP 签名⽰例 1
/**
2
* 签名并获取URL结果,json格式返回
3
*
4
* 1. 查询弹性IP列表, DescribeAddresses
5
* 2. 解绑弹性IP, DisassociateAddress
6
* 3. 释放弹性IP, ReleaseAddresses
7
* 4. 公⽹IP转弹性IP, TransformAddress
8
*
9
* @param string $req_action : DescribeAddresses, DisassociateAddress, ReleaseAddresses, TransformAddress
10
* @param string $params : 以 & 开头, 如 &xxx=yyy
11
*/function 12
13
14
15
16
17
18
19
20
qcloud_eip_sign($req_action='DescribeAddresses',
$req_region='ap-beijing',
$req_extra_params='',
$retry_NUM=3) {
global$QCloud_SecretId;
global$QCloud_SecretKey;
21
// $req_action='DescribeAddresses' 22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
$req_signature=
$req_signature_method=
'HmacSHA256';
// HmacSHA1(默认), HmacSHA256$req_secretid=
$QCloud_SecretId;
// 密钥ID,⽤作参数
$req_secretkey=
$QCloud_SecretKey;
// 密钥key,⽤作加密
$req_timestamp=
strtotime(date('YmdHis'));
// 1402992826
$req_nonce= rand(1000, 1000000);
// 随机正整数
$req_version=
'2017-03-12';
$req_api=
'/v2/';// $req_region = 'ap-beijing'; // ap-guangzhou
$req_method=
'GET';
// GET POST'' 44
45
// $req_uri = "/v2/?Action=DescribeAddresses 46
47
// &Region=ap-beijing 48
49
// &Signature=pStJagaKsV2QdkJnBQWYBDByZ9YPBsOi 50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
$req_signature= urlencode(
$req_uri= sprintf("%s%s?%s",
$req_method,
$req_api,
$req_params2);
$req_params2= implode("&",
$req_params_array);sort($req_params_array);
// 以value排序,value值为 Action=DescribeAddresses 、 Region=ap-beijing
$req_params_array=
explode("&",
$req_params);
// &SecretId=AKIDpY8cxBD2GLGK9sT0LaqIczGLFxTsoDF6
// 请求⽅法 + 请求主机 +请求路径 + ? + 请求字符串
$req_params= sprintf("Action=%s&Region=%s&Version=%s&Timestamp=%s&Nonce=%s&SecretId=%s&SignatureMethod=%s%s",
$req_action,
$req_region,
$req_version,
$req_timestamp,
$req_nonce,
$req_secretid,
$req_signature_method,
$req_extra_params);// &Timestamp=1402992826// &Nonce=345122// &Version=2017-03-12// &AddressIds.1=eip-hxlqja90
;
76
77
78
base64_encode(hash_hmac('sha256',
$req_uri,
$req_secretkey, true)));
// urlencode(xxx)
79
80
81
$req_url= sprintf("%s?%s&Signature=%s",
$req_api,
$req_params2,
$req_signature);
$res= curl_url($req_url);
$retry_idx= 0;
while(empty($res) &&
$retry_idx<
$retry_NUM) {
$retry_idx+= 1;
$res= curl_url($req_url);
}
if(!empty($res)) {
$resJson= json_decode($res, true);
$resJson=
$resJson['Response'];
echosprintf("
+++++ action : %s
resJson: ",
$req_action);
print_r($resJson);
return$resJson;
}
else{
returnnull;
}}
$req_action_query=
'DescribeAddresses';
// 查询弹性IP$req_action_unbind=
'DisassociateAddress';
// 解绑弹性IP$req_action_release=
'ReleaseAddresses';
// 释放弹性IP$req_action_transform=
'TransformAddress';
// 公⽹IP转弹性IP
$req_region=
'ap-guangzhou';$req_extra_params=
'';
// 1. 查询弹性IP列表$resJson= qcloud_eip_sign($req_action_query,
$req_region);var_dump($resJson);
运⾏结果: 1
2
3
4
req_url: /v2/?Action=DescribeAddresses&Nonce=585269&Region=ap-guangzhou&SecretId=AKIDSmAAAA2DABCDpTkBBBBMLMFwY0HM1234&SignatureMethod=HmacSHA256&Timestamp=1520429723&Version=201
array (size=3)
5
6
7
8
9
10
11
12
13
'TotalCount'=> int 1
'AddressSet'=>
array (size=1)
0 =>
array (size=11)
'AddressId'=> string
'eip-qy123abc'(length=12)
'AddressName'=> null
14
15
'AddressIp'=> string
'111.230.123.234'(length=15)
16
17
'AddressStatus'=> string
'BIND'(length=4)
18
19
'InstanceId'=> string
'ins-fabc1234'(length=12)
20
'NetworkInterfaceId'=> null
'PrivateAddressIp'=> string
'10.104.245.26'(length=14)
'IsArrears'=> boolean
false
'IsBlocked'=> boolean
false
'IsEipDirectConnection'=> boolean
false
'CreatedTime'=> string
'2018-03-07T12:46:26Z'(length=20)
'RequestId'=> string
'ad28067e-d1f9-4c47-932e-6bba1d123456'(length=36) 代码说明:1)函数抽象封装签名⽅法,⽅便管理维护,减少开发⼯作量2)参数按照升序排列 explode(xxx) —> sort($req_params_array) —> implode(xxx)3)签名⽅法,需要添加 urlencode,否则经常提⽰签名错误,原因是未urlencode会有⼀些 空格、加号(+)、等号(=)等特殊字符$req_signature = urlencode(base64_encode(hash_hmac('sha256', $req_uri, $req_secretkey, true))); // urlencode(xxx)
Python 签名⽰例 1
#!/usr/bin/env python# -*- coding:utf-8 -*- 2
3
# 2018-01-08 4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
rs
importsysreload(sys)aultencoding('utf-8')
## 腾讯云API接⼝签名defqcloud_eip_sign(req_action='DescribeAddresses', req_region='ap-beijing', req_extra_params='', retry_NUM=3):
req_method
='GET'
# GET POST
req_api
='/v2/'
req_version
=importloggingimporthashlib, base64, hmac, randomimporturllib, urllib2importtime, datetime, os, json
## 28
'2017-03-12'
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
req_timestamp
=int(())
# 1520422452
req_nonce
=t(1000,
1000000)
# 随机正整数
req_secretid
=QCLOUD_SecretId
# 密钥ID,⽤作参数
req_secretkey
=QCLOUD_SecretKey
# 密钥key,⽤作加密
req_signature_method
='HmacSHA256'
# HmacSHA1(默认), HmacSHA256
req_signature
=''
# req_uri = "/v2/?Action=DescribeAddresses# &Version=2017-03-12 44
45
# &Timestamp=1402992826 46
47
# &SecretId=AKIDpY8cxBD2GLGK9sT0LaqIczGLFxTsoDF6 48
49
50
51
52
53
54
55
56
57
58
59
req_params
="Action=%s&Region=%s&Version=%s&Timestamp=%s&Nonce=%s&SecretId=%s&SignatureMethod=%s%s"%(req_action, req_region, req_version, req_timestamp, req_nonce, req_secretid, req_signature_method, req_extra_params)
req_params_array
=req_('&')
req_params_array
=sorted(req_params_array)
# 以value排序,value值为 Action=DescribeAddresses 、 Region=ap-beijing
req_params2
=
# 请求⽅法 + 请求主机 +请求路径 + ? + 请求字符串
# &Nonce=345122# &Signature=pStJagaKsV2QdkJnBQWYBDByZ9YPBsOi# &AddressIds.1=eip-hxlqja90# &Region=ap-beijing'&' 60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
req_url
="%s?%s&Signature=%s"%(req_api, req_params2, req_signature)
('qcloud_eip_sign() - req_url: %s'%(req_url))
res
=spider_url(req_url)
retry_idx
=0;
whilenotres
andretry_idx < retry_NUM:
retry_idx
+=1
res
=spider_url(req_url)
ifres :
resJson
=(res)
resJson
=resJson['Response']
print"
+++++ action : %s
resJson: "%(req_action,)
req_uri
="%s%s?%s"%(req_method, req_api, req_params2)
req_signature
=( base64.b64encode((req_secretkey, req_uri, digestmod=256).digest()) )
# (xxx).join(req_params_array);
returnresJson
else:
returnNone;
if__name__
=="__main__":
req_action_query
='DescribeAddresses'
# 查询弹性IP
req_action_unbind
='DisassociateAddress'
# 解绑弹性IP
req_action_release
='ReleaseAddresses'
# 释放弹性IP
req_action_transform
='TransformAddress'
# 公⽹IP转弹性IP
req_region='ap-guangzhou'
req_extra_params
='';
# 1. 查询弹性IP列表
resJson
=qcloud_eip_sign(req_action_query, req_region)
(resJson)
运⾏结果: 1
2
3
req_url: /v2/index/rpIbQ5jPfe9tW3w9Slom4%3D
.php?Action=DescribeAddresses&Nonce=383782&Region=ap-guangzhou&SecretId=AKIDSmAAAA2DABCDpTkBBBBMLMFwY0HM1234&SignatureMethod=HmacSHA256&Timestamp=1520430569&Version=201 4
{ 5
6
"Response": {
7
8
9
10
11
12
13
"TotalCount": 1,
"AddressSet": [
{
"AddressId":
"eip-qy123abc",
"AddressName": null,
14
15
"AddressIp":
"111.230.123.234",
16
17
"AddressStatus":
"BIND",
18
19
"InstanceId":
"ins-fabc1234",
20
21
22
23
"NetworkInterfaceId": null,
"PrivateAddressIp":
"10.104.245.26",
"IsArrears":
false,
"IsBlocked":
false,
"IsEipDirectConnection":
false,
"CreatedTime":
"2018-03-07T12:46:26Z"
}
],
"RequestId":
"c2ab3f7f-9796-4ade-afb1-6bba1d123456"
}}
代码说明:1)Python改写PHP代码,有⼀些细节,如 int(())、t(1000, 1000000)、sorted(req_params_array)等2)参数按照升序排列 ('&') —> sort($req_params_array) —> '&'.join(xxx)3)签名⽅法,需要添加 、base64.b64encode(xxx)、digest() 等,否则经常提⽰签名错误req_signature = ( base64.b64encode((req_secretkey, req_uri, digestmod=256).digest()) ) # (xxx)
Python 代码⾥,特别要注意 hmac 签名 sha256 后获取的是 digest(),⽽不是 hexdigest() 这⾥错了会⼀直提⽰签名错误!总结之PHP和Python的对应关系1) PHP 签名 1
// sha1$hmac_sha1_str 2
3
4
5
=
base64_encode(hash_hmac("sha1",
$data,
$secret_access_key));
// HMAC-SHA1加密$signature 6
7
= urlencode($hmac_sha1_str);
// 编码URL
// sha256$hmac_sha256_str=
base64_encode(hash_hmac("sha256",
$data,
$secret_access_key));
// HMAC-SHA256加密$signature= urlencode($hmac_sha256_str);
// 编码URL
2)Python 签名 1
2
3
importurllib, base54, hashlib, hmac
# sha1hmac_sha1_str
4
5
=base64.b64encode( (secret_access_key, data, digestmod=1).digest() )signature
6
7
8
=(hmac_sha1_str)
# sha256hmac_sha256_str
9
10
11
=base64.b64encode( (secret_access_key, data, digestmod=256).digest() )signature
=(hmac_sha256_str) 12
13
14
# sha256hmac_sha256_str
=base64.b64encode( (secret_access_key, data, digestmod=256).hexdigest() )
# 16进制,错误signature
=(hmac_sha256_str)
发布者:admin,转转请注明出处:http://www.yc00.com/news/1688932303a184932.html
评论列表(0条)