Python

云 API 签名方法

2019-02-10  本文已影响20人  红色火苗

整体说明

本实验,将会通过 Python 语言,以云服务器 > 查询地域列表为例,进行签名,鉴权的简单实现,同时进行测试,最终获得到预期结果。 请在操作本实验之前,自己提前获取好密钥信息,并且替换掉本文中的测试密钥。

必备环境和工具

请确保已经安装了 Python 等。 可以通过:

python3 --version

或者:

python --version

来看一下 python 的版本。

准备密钥

通过网页:https://console.cloud.tencent.com/capi 获得秘钥信息(SecretId和SecretKey) 例如我的:

SecretId:

AKIDGRSHz3e17HVaVEeEWddR4Wr1zmNld5yk

SecretKey:

rY5VmsobGoBM2YsFWcXG0c3HMI2f6OVU

SecretId 用于标识 API 调用者身份 SecretKey 用于加密签名字符串和服务器端验证签名字符串的密钥。 用户必须严格保管安全凭证,避免泄露。 API 密钥是构建腾讯云 API 请求的重要凭证,使用腾讯云 API 可以操作您名下的所有腾讯云资源,为了您的财产和服务安全,请妥善保存和定期更换密钥,当您更换密钥后,请及时删除旧密钥。

签名理论实现

任务时间:时间未知

获得参数信息

参数名 是否必填 参数类型
Action String
Version String
Region String
参数名 是否必填 参数类型
Action String
Region String
Timestamp Integer
Nonce Integer
SecretId String
Signature String
Version String
SignatureMethod String
Token String
参数名 是否必填 参数类型
Action String
Version String
Timestamp Integer
Nonce Integer
SecretId String

进行参数排序:

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

参数名 是否必填 参数类型
Action String
Nonce Integer
SecretId String
Timestamp Integer
Version String

字典形式:

{ 
    'Action' : 'DescribeRegions’, 
    'Nonce' : 11886,
    'SecretId' : 'AKIDGRSHz3e17HVaVEeEWddR4Wr1zmNld5yk',
     'Timestamp' : 1465185768, 
    'Version' : '2017-03-12', 
}

组成字符串

Action=DescribeRegions&
Nonce=11886&
SecretId=AKIDGRSHz3e17HVaVEeEWddR4Wr1zmNld5yk&
Timestamp=1465185768
Version=2017-03-12&

  1. 请求方法: 支持 POST 和 GET 方式,这里使用 GET 请求,注意方法为全大写。

  2. 请求主机:查看实例列表(DescribeInstances)的请求域名为:cvm.tencentcloudapi.com。实际的请求域名根据接口所属模块的不同而不同,详见各接口说明。

  3. 请求路径: 当前版本云 API 的请求路径固定为 / 。

  4. 请求字符串: 即上一步生成的请求字符串。

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

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

GETcvm.tencentcloudapi.com/?Action=DescribeRegions&Nonce=11886&SecretId=AKIDGRSHz3e17HVaVEeEWddR4Wr1zmNld5yk&Timestamp=1465185768&Version=2017-03-12

加密生成签名串

此步骤生成签名串。 首先使用 HMAC-SHA1 算法对上一步中获得的签名原文字符串进行签名,然后将生成的签名串使用 Base64 进行编码,即可获得最终的签名串。

签名代码实现

任务时间:时间未知

建立文件

vim demo_1.py

输入密钥信息

例如: 请注意将密钥信息修改成自己的!

SecretId = "AKIDGRSHz3e17HVaVEeEWddR4Wr1zmNld5yk"
SecretKey = "rY5VmsobGoBM2YsFWcXG0c3HMI2f6OVU"

填写必须信息

import time
uri = "cvm.tencentcloudapi.com"
paramDict = {
    "Action":"DescribeRegions",
    "Version":"2017-03-12",
    "SecretId":SecretId,
    "Nonce":123456,
    "Timestamp":int(time.time()),
}

排序

tempList = []
tempDict = {}
for eveKey, eveValue in paramDict.items():
    tempLowerData = eveKey.lower()
    tempList.append(tempLowerData)
    tempDict[tempLowerData] = eveKey
tempList.sort()

resultList = []
for eveData in tempList:
    tempStr = str(tempDict[eveData]) + "=" + str(paramDict[tempDict[eveData]])
    resultList.append(tempStr)

第一次字符串拼接

sourceStr = "&".join(resultList)

第二次字符串拼接

requestStr = "%s%s%s%s%s"%("GET", uri, "/", "?", sourceStr)

SHA1 加密

import sys
if sys.version_info[0] > 2:
    signStr = requestStr.encode("utf-8")
    SecretKey = SecretKey.encode("utf-8")

import hashlib
digestmod = hashlib.sha1

import hmac
hashed = hmac.new(SecretKey, signStr, digestmod)

Base64编码

import binascii
base64Data = binascii.b2a_base64(hashed.digest())[:-1]

if sys.version_info[0] > 2:
    base64Data = base64Data.decode()

GET请求还需要URL编码

import urllib.parse
base64Data = urllib.parse.quote(base64Data)

对签名结果测试

任务时间:时间未知

生成请求url

url = "https://" + uri + "/" + "?" + sourceStr + "&Signature=" + base64Data

发起请求,并将结果变成Json格式

import urllib.request
import json
for eveData in json.loads(urllib.request.urlopen(url).read().decode("utf-8"))["Response"]["RegionSet"]:
    print(eveData)

保存上面的文件

请注意将密钥信息修改成自己的!

SecretId = "AKIDGRSHz3e17HVaVEeEWddR4Wr1zmNld5yk"
SecretKey = "rY5VmsobGoBM2YsFWcXG0c3HMI2f6OVU"

'''
Timestamp Integer 是 当前 UNIX 时间戳,可记录发起 API 请求的时间。例如1529223702,如果与当前时间相差过大,会引起签名过期错误。
Nonce Integer 是 随机正整数,与 Timestamp 联合起来,用于防止重放攻击。
SecretId String 是 在云API密钥上申请的标识身份的 SecretId,一个 SecretId 对应唯一的 SecretKey ,而 SecretKey 会用来生成请求签名 Signature。
Action 是 String 公共参数,本接口取值:DescribeRegions
Version 是 String 公共参数,本接口取值:2017-03-12
'''
import time
uri = "cvm.tencentcloudapi.com"
paramDict = {
    "Action":"DescribeRegions",
    "Version":"2017-03-12",
    "SecretId":SecretId,
    "Nonce":123456,
    "Timestamp":int(time.time()),
}

tempList = []
tempDict = {}
for eveKey, eveValue in paramDict.items():
    tempLowerData = eveKey.lower()
    tempList.append(tempLowerData)
    tempDict[tempLowerData] = eveKey
tempList.sort()

resultList = []
for eveData in tempList:
    tempStr = str(tempDict[eveData]) + "=" + str(paramDict[tempDict[eveData]])
    resultList.append(tempStr)

sourceStr = "&".join(resultList)

requestStr = "%s%s%s%s%s"%("GET", uri, "/", "?", sourceStr)

import sys
if sys.version_info[0] > 2:
    signStr = requestStr.encode("utf-8")
    SecretKey = SecretKey.encode("utf-8")

import hashlib
digestmod = hashlib.sha1

import hmac
hashed = hmac.new(SecretKey, signStr, digestmod)

import binascii
base64Data = binascii.b2a_base64(hashed.digest())[:-1]

if sys.version_info[0] > 2:
    base64Data = base64Data.decode()

import urllib.parse
base64Data = urllib.parse.quote(base64Data)

url = "https://" + uri + "/" + "?" + sourceStr + "&Signature=" + base64Data
print(url)

import urllib.request
import json
for eveData in json.loads(urllib.request.urlopen(url).read().decode("utf-8"))["Response"]["RegionSet"]:
    print(eveData)

:wq

python3 demo_1.py

image

至此,我们完成了签名过程,并进行了相关的验证。

上一篇 下一篇

猜你喜欢

热点阅读