在调用阿里云 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. pytest_demo_实战1

    1.根目录配置 pytest.ini [pytest] addopts = -p no:warnings 2.更改运行手势,系统配置 file -> setting -> Tools -& ...

  2. com.fasterxml.jackson.core.JsonGenerationException: Can not write a field name, expecting a value异常

    springboot对象返回,一直报生成json异常,经过检查,发现是自己在做xss防护时对出参进行了json的处理(copy代码不可取,囧) 异常信息 这里进行了出参处理了,但实际上只要对入参处理就 ...

  3. java 精彩文章收集

    hashCode() 和equals() 区别和作用 字符串常量池 Java集合之LinkedHashMap

  4. SharpImage图像特效和合成类库介绍

    SharpImage是用于.NET(C#.VB)的专业图像特效以及图像合成类库.借助它,您可以快速实现Photoshop滤镜效果以及图层合成. 1.内置50+种图像特效滤镜.(如亮度.对比度.负片.图 ...

  5. virtualbox通过Nat模式上网,宿主机与宿主机互通

    本地搭建virtualbox,开始用的nat转发模式,这样的话宿主机没法访问虚拟机里面的服务.比如nginx网站.这样很不方便 . 在网上找了好久,终于找到了方案.那就是再添加一块虚拟网卡. 在虚拟机 ...

  6. 关于在linux上部署scrapy的爬虫

    1.在服务器中安装chrome sudo apt-get install libxss1 libappindicator1 libindicator7 wget https://dl.google.c ...

  7. JS面向对象设计-创建对象

    Object构造函数和对象字面量都可以用来创建单个对象,但是在创建多个对象时,会产生大量重复代码. 1.工厂模式 工厂模式抽象了创建具体对象的过程.由于ECMAScript无法创建类,我们用函数来封装 ...

  8. 26.Apache Solr RCE

    多事之秋,刚爆出来shiro的RCE,紧接着solr服务器就出了RCE 自从漏洞爆出来已经一段时间,复现漏洞多如牛毛,我这里来水一篇 漏洞简介 什么是solr服务器? Solr是一个独立的企业级搜索应 ...

  9. android 实时获取网速

    public class NetSpeed { private static final String TAG = NetSpeed.class.getSimpleName(); private lo ...

  10. springboot入门介绍

    1. SpringBoot学习之@SpringBootApplication注解 下面是我们经常见到SpringBoot启动类代码: @SpringBootApplicationpublic clas ...