美文网首页Python
云 API 签名方法

云 API 签名方法

作者: 红色火苗 | 来源:发表于2019-02-10 13:48 被阅读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 可以操作您名下的所有腾讯云资源,为了您的财产和服务安全,请妥善保存和定期更换密钥,当您更换密钥后,请及时删除旧密钥。

签名理论实现

任务时间:时间未知

获得参数信息

  • 以云服务器 CVM 查询地域列表为例,获取他的参数信息:
参数名 是否必填 参数类型
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 参数,其参数名称为"Action",参数值为"DescribeInstances",因此格式化后就为 Action=DescribeInstances 。 注意:“参数值”为原始值而非url编码后的值。
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

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

相关文章

网友评论

    本文标题:云 API 签名方法

    本文链接:https://www.haomeiwen.com/subject/uaateqtx.html