在调用阿里云 API 的时候,最让人头疼的就是 API 的签名(Signature)机制,阿里云在通用文档中也有专项说明,但是仅仅有基于 Java 的实现代码示例。所以这里基于 Python 来分析下。

基本步骤

  1. 构造规范化的请求字符串 (Canonicalized Query String)
  2. 构造被签名字符串 StringToSign
  3. 计算 HMAC 值
  4. 计算签名值
  5. 添加签名
    理论部分的详细内容参考阿里云官方帮助文档

具体 Python 实现

API 请求原理

简单来说调用阿里云 API 就是一个 http 请求(大多数为 GET, 这里也是基于 GET 请求),只是后面要跟一堆参数,例如一个查看快照的请求为:

http://ecs.aliyuncs.com/?SignatureVersion=1.0&Format=JSON&Timestamp=2017-08-07T05%3A50%3A57Z&RegionId=cn-hongkong&AccessKeyId=xxxxxxxxx&SignatureMethod=HMAC-SHA1&Version=2014-05-26&Signature=%2FeGgFfxxxxxtZ2w1FLt8%3D&Action=DescribeSnapshots&SignatureNonce=b5046ef2-7b2b-11e7-a3c5-00163e001831&ZoneId=cn-hongkong-b

请求中所需要的公共参数(就是调用 API 都需要用到的参数)为:

SignatureVersion # 签名算法版本,目前为 1.0
Format # 返回消息的格式化方式,JSON or XML 默认值为 XML
Timestamp # 请求的时间戳,UTC时间,例如: 2013-01-10T12:00:00Z
AccessKeyId # 账号密钥 ID
SignatureMethod # 签名方式,目前为 HMAC-SHA1
Version # 版本号,为日期形式,例如: 2014-05-26 每个产品不同
Signature # 最难搞定的签名
SignatureNonce # 唯一随机数,防止网络攻击。不同请求间使用不同的随机数。

除了 Signature 之外,其它的参数都比较容易获得,有些甚至是固定的值,具体可以参考阿里云文档

除了公共参数之外,还需要具体接口(Action)的请求参数,每个 Action 接口的参数可以参考对应产品的接口文档,例如 DescribeLoadBalancers

Signature 是基于公共参数和接口参数的,所以比较复杂。

Signature 具体代码实现

构造规范化的请求字符串 (Canonicalized Query String)

  • 构造 dict
    Python 中体现参数一一对应的就是 dict, 创建一个 dict, 把请求参数些进去,这里简化参数只有这些:
>>> D = {
'Format':'JSON',
'Version':'2014-05-26',
'SignatureMethod':'HMAC-SHA1'
}
  • 排序
    由于签名要求唯一性,包括顺序,所以需要按照参数名称排序
>>> sortedD = sorted(D.items(), key=lambda x: x[0])
>>> sortedD
[('Format', 'JSON'),
('SignatureMethod', 'HMAC-SHA1'),
('Version', '2014-05-26')] # 先通过 D.items() 转化为 List, 然后利用 sorted 方式按照 key 排序
  • URL 编码
    由于在标准请求字符串中需要使用 UTF-8 字符集,对请求参数名称和值中有些不符合规范的字符要进行 url 编码,具体规则为:

字符 AZ、az、0~9 以及字符“-”、“_”、“.”、“~”不编码;
其它字符编码成 %XY 的格式,其中 XY 是字符对应 ASCII 码的 16 进制表示。比如英文的双引号(”)对应的编码为 %22;
对于扩展的 UTF-8 字符,编码成 %XY%ZA… 的格式;
英文空格( )要编码成 %20,而不是加号(+)。

注意:一般支持URL编码的库(比如 Java 中的 java.net.URLEncoder)都是按照 “application/x-www-form-urlencoded”的 MIME 类型的规则进行编码的。实现时可以直接使用这类方式进行编码,把编码后的字符串中加号(+)替换成 %20、星号(*)替换成 %2A、%7E 替换回波浪号(~),即可得到上述规则描述的编码字符串。

这里使用 python 中的 urllib 库来进行编码:

>>> def percentEncode(str):
res = urllib.quote(str.decode(sys.stdin.encoding).encode('utf8'), '')
res = res.replace('+', '%20')
res = res.replace('*', '%2A')
res = res.replace('%7E', '~')
return res
# 这里构造一个编码函数,对一个字符串进行编码,返回编码后的字符串
  • 生成标准化请求字符串
>>> canstring = ''
>>> for k,v in sortedD:
canstring += '&' + percentEncode(k) + '=' + percentEncode(v)
>>> canstring
'&Format=JSON&SignatureMethod=HMAC-SHA1&Version=2014-05-26'

构造被签名字符串 StringToSign

规则为:

StringToSign=
HTTPMethod + “&” +
percentEncode(“/”) + ”&” +
percentEncode(CanonicalizedQueryString)

所以在这个实例中

>>> stringToSign = 'GET&%2F&' + percentEncode(canstring[1:])
>>> stringToSign
'GET&%2F&Format%3DJSON%26SignatureMethod%3DHMAC-SHA1%26Version%3D2014-05-26'
# >>> percentEncode(“/”)
# %2F

计算 HMAC 值

>>> access_key_secret = 'access_key_secret'
>>> h = hmac.new(access_key_secret + "&", stringToSign, sha1)
>>> h
<hmac.HMAC instance at 0x35ed440>
# access_key_secret 是通过阿里云账号中的 AK 中获取的,和 access_key_id 对应,测试的时候使用的是 'access_key_secret'

计算签名值

>>> signature = base64.encodestring(h.digest()).strip()
>>> signature
'sq8LVH+ZItZiVQ0/rVnHV1kP/BE='

到此生成了 signature 签名

添加签名

>>> D['Signature'] = signature
>>> D
{'Format': 'JSON',
'Signature': 'sq8LVH+ZItZiVQ0/rVnHV1kP/BE=',
'SignatureMethod': 'HMAC-SHA1',
'Version': '2014-05-26'}

所以在这个实例中,最终请求的 url 为

>>> url = 'http://ecs.aliyuncs.com/?' + urllib.urlencode(D)
>>> url
'http://ecs.aliyuncs.com/?SignatureMethod=HMAC-SHA1&Version=2014-05-26&Signature=sq8LVH%2BZItZiVQ0%2FrVnHV1kP%2FBE%3D&Format=JSON'

拿到浏览器直接访问即可,得到结果为:

{"Message":"The input parameter \"Action\" that is mandatory for processing this request is not supplied.","RequestId":"129880D4-710D-4D2C-9F8B-12777FA1D3C6","HostId":"ecs.aliyuncs.com","Code":"MissingParameter"}

由于是测试环境,就给了三个参数,所以还少很多参数,正常来说把这些参数都加上,然后生成 signature,组成 url 后直接访问就可以得到结果。

文档 来自:https://www.jianshu.com/p/7574349a5042

阿里云 API 签名机制的 Python 实现的更多相关文章

  1. 阿里云 API调用实践(python语言)

    1.结论:阿里云的SDK开发,其实就是远程调用API,python的代码就是一个外壳,核心是封装成一个http报文,利用json格式,进行RPC调用. 2.SDK调用API的套路如下: # -*- c ...

  2. 阿里云视频直播API签名机制源码

    阿里云视频直播API签名机制源码 本文展示:通过代码实现下阿里视频直播签名处理规则 阿里云视频直播签名机制,官方文档链接:https://help.aliyun.com/document_detail ...

  3. Python 调用阿里云 API 收集 ECS 数据

    #!/usr/bin/env python # coding: utf-8 # author: Wang XiaoQiang ''' 功能介绍: 1.调用阿里云API,收集所有区域 ECS 信息 2. ...

  4. 【阿里云API】 阿里云API调用的若干说明

    阿里云API 为了监控我们使用的一些阿里云产品,需要些一些脚本,定时调用这些脚本来获得相关阿里云产品的信息. ■ 概述 调用阿里云API大约分成两类方法,一个是直接从HTTP协议开始,自己根据阿里云的 ...

  5. 阿里云API网关(9)常见问题

    网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...

  6. 阿里云API网关!

    API 网关(API Gateway)提供高性能.高可用的 API 托管服务,帮助用户对外开放其部署在 ECS.容器服务等阿里云产品上的应用,提供完整的 API 发布.管理.维护生命周期管理.用户只需 ...

  7. 浅析阿里云API网关的产品架构和常见应用场景

    自上世纪60年代计算机网络发展开始,API(Application Programming Interface )随之诞生,API即应用程序接口,是实现系统间衔接的桥梁.时至今日,API市场已经形成了 ...

  8. 阿里云API网关(11)外网访问 阿里云API网关内定义的API步骤:

    网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...

  9. 阿里云物联网平台体验(树莓派+Python篇)

    阿里云物联网平台体验(树莓派+Python篇) 虽然对阿里云物联网平台比较熟悉了,从一开始就有幸参与了飞凤平台(Link Develop 一站式开发平台的前身)的一些偏硬件接入的工作.但是同时也见证了 ...

随机推荐

  1. KVM学习

    获取镜像目前大小 # qemu-img info debian.img 添加额外的10G空间到镜像中 # qemu-img resize -f raw debian.img +10GB 注意:并不是所 ...

  2. eclipse自定义导入或者编写版本格式化 xml

    1.自定义或者自己导入版本格式 window——preferences——java——Code style ——formatter(New 或者 import)

  3. MarkDown 常用语法规则

    > # 标题 # 标题1:h1的效果 ## 标题2:h2的效果 ### 标题3:h3的效果 #### 标题4:h4的效果 ##### 标题5:h5的效果 ###### 标题6:h6的效果 ### ...

  4. 25个特殊操作符(special operator)

    1. CLHS (Common-Lisp-Hyper-Spec) http://www.lispworks.com/documentation/HyperSpec/Body/03_ababa.htm ...

  5. 【selenium】基于python语言,如何用select选择下拉框

    在项目测试中遇到了下拉框选择的控件,来总结下如何使用select选择下拉框: 下图是Select类的初始化描述,意思是,给定元素是得是select类型,不是就抛异常.接下来给了例子:要操作这个sele ...

  6. 解决Eclipe安装不上android的ADT的办法

    Eclipse,https://dl-ssl.google.com/android/eclipse/安装不上去,ADT在线安装装不了,用离线包又出问题时会不会疯掉. 显然,国内网络和谐掉了google ...

  7. javascript高级程序设计学习历程

    第三章 基本概念 3.1 语法 3.1.1 区分大小写 ECMAScript中的一切(变量,函数,操作符)都区分大小写的 3.1.2 标识符 标识符:变量,函数,属性的名字以及函数的参数. 标识符的命 ...

  8. Qt Examples - Boxes (在Qt场景视图中结合OpenGL渲染)

    QT自带例程Boxes使用QT Graphics View框架实现了2D图形和3D图形的混合渲染,综合性比较强,整合知识较多,值得学习. 可以使用鼠标通过以下方式控制演示中的元素: 按住鼠标左键的同时 ...

  9. 尚硅谷MySQL高级学习笔记

    目录 数据库MySQL学习笔记高级篇 写在前面 1. mysql的架构介绍 mysql简介 mysqlLinux版的安装 mysql配置文件 mysql逻辑架构介绍 mysql存储引擎 2. 索引优化 ...

  10. MySQL数据备份概述

    MySQL备份类型 热备份.温备份.冷备份 (根据服务器状态) 热备份:读.写不受影响: 温备份:仅可以执行读操作: 冷备份:离线备份:读.写操作均中止: 物理备份与逻辑备份 (从对象来分) 物理备份 ...