阿里云 API 簽名機(jī)制的 Python 實(shí)現(xiàn)


在調(diào)用阿里云 API 的時(shí)候,最讓人頭疼的就是 API 的簽名(Signature)機(jī)制略吨,阿里云在通用文檔中也有專項(xiàng)說明,但是僅僅有基于 Java 的實(shí)現(xiàn)代碼示例。所以這里基于 Python 來分析下发皿。

基本步驟

  1. 構(gòu)造規(guī)范化的請求字符串 (Canonicalized Query String)
  2. 構(gòu)造被簽名字符串 StringToSign
  3. 計(jì)算 HMAC 值
  4. 計(jì)算簽名值
  5. 添加簽名
    理論部分的詳細(xì)內(nèi)容參考阿里云官方幫助文檔

具體 Python 實(shí)現(xiàn)

API 請求原理

簡單來說調(diào)用阿里云 API 就是一個(gè) http 請求(大多數(shù)為 GET, 這里也是基于 GET 請求),只是后面要跟一堆參數(shù)拂蝎,例如一個(gè)查看快照的請求為:

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

請求中所需要的公共參數(shù)(就是調(diào)用 API 都需要用到的參數(shù))為:

SignatureVersion # 簽名算法版本穴墅,目前為 1.0 
Format # 返回消息的格式化方式,JSON or XML 默認(rèn)值為 XML
Timestamp # 請求的時(shí)間戳温自,UTC時(shí)間玄货,例如: 2013-01-10T12:00:00Z 
AccessKeyId # 賬號密鑰 ID
SignatureMethod # 簽名方式,目前為 HMAC-SHA1
Version # 版本號悼泌,為日期形式松捉,例如: 2014-05-26 每個(gè)產(chǎn)品不同
Signature # 最難搞定的簽名
SignatureNonce # 唯一隨機(jī)數(shù),防止網(wǎng)絡(luò)攻擊券躁。不同請求間使用不同的隨機(jī)數(shù)惩坑。

除了 Signature 之外,其它的參數(shù)都比較容易獲得也拜,有些甚至是固定的值以舒,具體可以參考阿里云文檔

除了公共參數(shù)之外,還需要具體接口(Action)的請求參數(shù)慢哈,每個(gè) Action 接口的參數(shù)可以參考對應(yīng)產(chǎn)品的接口文檔蔓钟,例如 DescribeLoadBalancers

Signature 是基于公共參數(shù)和接口參數(shù)的,所以比較復(fù)雜卵贱。

Signature 具體代碼實(shí)現(xiàn)

構(gòu)造規(guī)范化的請求字符串 (Canonicalized Query String)

  • 構(gòu)造 dict
    Python 中體現(xiàn)參數(shù)一一對應(yīng)的就是 dict, 創(chuàng)建一個(gè) dict, 把請求參數(shù)些進(jìn)去滥沫,這里簡化參數(shù)只有這些:
>>> D = {
    'Format':'JSON',
    'Version':'2014-05-26',
    'SignatureMethod':'HMAC-SHA1'
    }
  • 排序
    由于簽名要求唯一性,包括順序键俱,所以需要按照參數(shù)名稱排序
>>> sortedD = sorted(D.items(), key=lambda x: x[0])
>>> sortedD
[('Format', 'JSON'),
 ('SignatureMethod', 'HMAC-SHA1'),
 ('Version', '2014-05-26')]

# 先通過 D.items() 轉(zhuǎn)化為 List, 然后利用 sorted 方式按照 key 排序
  • URL 編碼
    由于在標(biāo)準(zhǔn)請求字符串中需要使用 UTF-8 字符集兰绣,對請求參數(shù)名稱和值中有些不符合規(guī)范的字符要進(jìn)行 url 編碼,具體規(guī)則為:

字符 AZ编振、az缀辩、0~9 以及字符“-”、“_”、“.”臀玄、“~”不編碼瓢阴;
其它字符編碼成 %XY 的格式,其中 XY 是字符對應(yīng) ASCII 碼的 16 進(jìn)制表示健无。比如英文的雙引號(”)對應(yīng)的編碼為 %22荣恐;
對于擴(kuò)展的 UTF-8 字符,編碼成 %XY%ZA… 的格式累贤;
英文空格( )要編碼成 %20叠穆,而不是加號(+)。

注意:一般支持URL編碼的庫(比如 Java 中的 java.net.URLEncoder)都是按照 “application/x-www-form-urlencoded”的 MIME 類型的規(guī)則進(jìn)行編碼的畦浓。實(shí)現(xiàn)時(shí)可以直接使用這類方式進(jìn)行編碼痹束,把編碼后的字符串中加號(+)替換成 %20、星號(*)替換成 %2A讶请、%7E 替換回波浪號(~)祷嘶,即可得到上述規(guī)則描述的編碼字符串。

這里使用 python 中的 urllib 庫來進(jìn)行編碼:

>>> 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
# 這里構(gòu)造一個(gè)編碼函數(shù)夺溢,對一個(gè)字符串進(jìn)行編碼论巍,返回編碼后的字符串    
  • 生成標(biāo)準(zhǔn)化請求字符串
>>> canstring = ''
>>> for k,v in sortedD:
        canstring += '&' + percentEncode(k) + '=' + percentEncode(v)
>>> canstring 
'&Format=JSON&SignatureMethod=HMAC-SHA1&Version=2014-05-26'

構(gòu)造被簽名字符串 StringToSign

規(guī)則為:

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

所以在這個(gè)實(shí)例中

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

計(jì)算 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 對應(yīng)风响,測試的時(shí)候使用的是 'access_key_secret'

計(jì)算簽名值

>>> 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'}

所以在這個(gè)實(shí)例中嘉汰,最終請求的 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'

拿到瀏覽器直接訪問即可,得到結(jié)果為:

{"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"}

由于是測試環(huán)境状勤,就給了三個(gè)參數(shù)鞋怀,所以還少很多參數(shù),正常來說把這些參數(shù)都加上持搜,然后生成 signature密似,組成 url 后直接訪問就可以得到結(jié)果。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末葫盼,一起剝皮案震驚了整個(gè)濱河市残腌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌贫导,老刑警劉巖抛猫,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異孩灯,居然都是意外死亡闺金,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門峰档,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掖看,“玉大人匣距,你說我怎么就攤上這事“タ牵” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵尚卫,是天一觀的道長归榕。 經(jīng)常有香客問我,道長吱涉,這世上最難降的妖魔是什么刹泄? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮怎爵,結(jié)果婚禮上特石,老公的妹妹穿的比我還像新娘。我一直安慰自己鳖链,他們只是感情好姆蘸,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著芙委,像睡著了一般逞敷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上灌侣,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天推捐,我揣著相機(jī)與錄音,去河邊找鬼侧啼。 笑死牛柒,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的痊乾。 我是一名探鬼主播皮壁,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼符喝!你這毒婦竟也來了闪彼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤协饲,失蹤者是張志新(化名)和其女友劉穎畏腕,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茉稠,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡描馅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了而线。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铭污。...
    茶點(diǎn)故事閱讀 38,599評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡恋日,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嘹狞,到底是詐尸還是另有隱情岂膳,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布磅网,位于F島的核電站谈截,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏涧偷。R本人自食惡果不足惜簸喂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望燎潮。 院中可真熱鬧喻鳄,春花似錦、人聲如沸确封。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽隅肥。三九已至竿奏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間腥放,已是汗流浹背泛啸。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留秃症,地道東北人候址。 一個(gè)月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像种柑,于是被迫代替她去往敵國和親岗仑。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理聚请,服務(wù)發(fā)現(xiàn)荠雕,斷路器,智...
    卡卡羅2017閱讀 134,628評論 18 139
  • https://nodejs.org/api/documentation.html 工具模塊 Assert 測試 ...
    KeKeMars閱讀 6,312評論 0 6
  • 下面的內(nèi)容基本都是我親測的 Xcode目錄位置:~/Library/Developer/Xcode/ Code S...
    Mr_Zander閱讀 330評論 0 1
  • 蕨菜比較多出現(xiàn)在地方在北方驶赏,在那里不少人將這種野菜喊做山珍炸卑,是飯桌上常見的一道菜,并且購買的價(jià)格還不低煤傍。之所以會如...
    執(zhí)筆青衫閱讀 683評論 0 0
  • 我們的人生道路雖然漫長盖文,但緊要處常常只有幾步。 ——柳青 人生何其短暫蚯姆,緊要的那幾步又是何其的關(guān)鍵...
    遙望江南閱讀 299評論 0 2