1. 程式人生 > WINDOWS開發 >Ali SDK API 相關

Ali SDK API 相關

Ali SDK API 相關
2018/11/19 Chenxin

基礎知識(SDK,API Explorer)

SDK API 區別
SDK更新肯定要慢些,需要阿里雲給出升級的SDK才可以使用.SDK是API的一種實現方式而已.
API更新會比較及時,因為無需打包成SDK釋出給使用者.只需要更新阿里雲伺服器端接收資料解析,以及對應的文件說明即可.SDK應該也是解析成API後發起到阿里雲的呼叫.

SDK簡單的示例程式碼(入門推薦)
阿里雲SDK各版本對應服務說明(不同服務都有一個SDK) https://develop.aliyun.com/tools/sdk?spm=a2c1g.8271268.10000.5.77a3df25JZvIkF#/python


阿里雲SDK python 簡易使用說明 https://help.aliyun.com/document_detail/53090.html?spm=a2c1g.8271268.10000.7.3f04df25RQ8QeL

SDK完整的示例程式碼即 阿里雲 API Explorer,其自動生成的SDK程式碼,是阿里雲推薦訪問API的方式,而非使用者手動的認證和簽名.
OpenApi 使用(對應SDK)說明,線上通過已登入使用者呼叫API.給出對應SDK使用程式碼,以及線上呼叫後的返回結果.
https://api.aliyun.com/?spm=a2c1g.8271268.10000.2.3f04df25RQ8QeL

SDK 的使用
比如-獲取例項資訊
使用OpenApi上自動生成的參考SDK程式碼示例方式(推薦,因為這個比較方便使用.直接在阿里提供的網站上就會自動生成)
從OpenApi上(

https://api.aliyun.com/?spm=a2c1g.8271268.10000.2.3f04df25RQ8QeL),可以自動生成的SDK程式碼,如下:

from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest
client = AcsClient(‘LTAI3b9Wpey0U0cc‘,‘kFV8tfHBKesPC1gMnglbxAdEygPys2‘,‘cn-shenzhen‘) # 這裡是keyid和secretkey

request = CommonRequest()
request.set_accept_format(‘json‘)
request.set_domain(‘ecs.aliyuncs.com‘)
request.set_method(‘POST‘)
request.set_version(‘2014-05-26‘)
request.set_action_name(‘DescribeInstances‘)

request.add_query_param(‘RegionId‘,‘cn-shenzhen‘)

response = client.do_action_with_exception(request)

python2: print(response)

print(str(response,encoding = ‘utf-8‘))

使用SDK說明文件裡的那個示例方式(不推薦,因為需要自己去挨個摸索)

from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkecs.request.v20140526 import DescribeInstancesRequest
from aliyunsdkecs.request.v20140526 import StopInstanceRequest

建立AcsClient例項

client = AcsClient(
"LTAI3b9Wpey0U0cc",# 這裡是金鑰
"kFV8tfHBKesPC1gMnglbxAdEygPys2",
"cn-shenzhen"
)

建立request,並設定引數

request = DescribeInstancesRequest.DescribeInstancesRequest()
request.set_PageSize(10)

發起API請求並顯示返回值

try:
response = client.do_action_with_exception(request)
print(response)
print(dir(response))
except ServerException as e:
print(e)
except ClientException as e:
print(e)

API使用-簽名認證
基本說明
如果需要各個服務的API HTTP方式呼叫,則需要到文件各個服務裡(比如ECS裡)去檢視API文件,裡面有對應的HTTP請求格式.
比如ECS API方式請求(格式,引數,簽名)-API- 請求結構說明

阿里雲 API 簽名機制的 Python 實現原理
參考
https://www.jianshu.com/p/7574349a5042 python2.X版本
https://help.aliyun.com/document_detail/27149.html?spm=a2c4g.11186623.6.639.39ce47d0ygIKdh 文件最下方,"附:python2.X版本簽名機制程式碼示例"

基本步驟

  1. 構造規範化的請求字串 (Canonicalized Query String)
  2. 構造被簽名字串 StringToSign
  3. 計算 HMAC 值
  4. 計算簽名值
  5. 添加簽名

其他說明
訪問的URL不需要排序.
構造待簽名字串 StringToSign 是需要按照ASCII碼排序(順序若與伺服器端不同,生成的簽名也會不同).

比如獲取例項狀態資訊URL

通過阿里雲API explorer(阿里雲提供的網頁) 方式獲得參考(順序可以隨機)
http://ecs.aliyuncs.com/
?
AccessKeyId=TMP.AQHo...npKl0HsZrE # 自動生成的一個臨時keyid
&Action=DescribeInstances
&Format=JSON
&RegionId=cn-shenzhen
&SecureTransport=true
&SignatureMethod=HMAC-SHA1
&SignatureNonce=386b2187986d4855c0efc08a985ff98c
&SignatureVersion=1.0
&SourceIp=118.112.75.132
&Timestamp=2018-11-19T07%3A44%3A22Z
&Version=2014-05-26
&Signature=O7ZnC7FzlGfjAMpD38RdkPRZSvw%3D

手動python建立的
https://ecs.aliyuncs.com/
?SignatureVersion=1.0
&Format=JSON
&TimeStamp=2018-11-21T08%3A28%3A17Z
&RegionId=cn-shenzhen
&AccessKeyId=LTAI3b9Wpey0U0cc
&SignatureMethod=HMAC-SHA1
&Version=2014-05-26
&Signature=YdudjAGoUKNkMP3KzPL9tSabqok%3D
&Action=DescribeInstances
&SignatureNonce=65512030-ed67-11e8-be20-8b2f931290aa

除了 Signature 之外,其它的引數都比較容易獲得,有些甚至是固定的值,具體可以參考阿里雲文件.

公共請求引數
請求中所需要的公共引數為:
AccessKeyId # 賬號金鑰 ID
Format # 返回訊息的格式化方式,JSON or XML 預設值為 XML
SignatureMethod # 簽名方式,目前為 HMAC-SHA1
SignatureNonce # 唯一隨機數,防止網路攻擊。不同請求間使用不同的隨機數。
SignatureVersion # 簽名演算法版本,目前為 1.0
Timestamp # 請求的時間戳,UTC時間,例如: 2013-01-10T12:00:00Z
Version # 版本號,為日期形式,例如: 2014-05-26 每個產品不同

Signature # 最難搞定的簽名(不屬於公共引數)

介面引數
除了公共引數之外,還需要具體介面(Action)的請求引數.每個 Action 介面的引數可以參考對應產品的介面文件,如Action=DescribeInstances

簽名
Signature 是基於公共引數和介面引數的,所以比較複雜。

具體實現
Signature 具體程式碼實現

1構造規範化請求字串 (Canonicalized Query String)

構造 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

這裡構造一個編碼函式,對一個字串進行編碼,返回編碼後的字串

生成規範化請求字串CanonicalizedQueryString

canstring = ‘‘
for k,v in sortedD:
canstring += ‘&‘ + percentEncode(k) + ‘=‘ + percentEncode(v)

canstring
‘&Format=JSON&SignatureMethod=HMAC-SHA1&Version=2014-05-26‘ #這裡的Canonicalized Query String 是包含&符號的(&沒有參與percentEncode)

2構造待簽名字串 StringToSign

規則為:
StringToSign=
HTTPMethod + “&” +
percentEncode(“/”) + ”&” +
percentEncode(CanonicalizedQueryString)

所以在這個例項中

stringToSign = ‘GET&%2F&‘ + percentEncode(canstring[1:]) #canstring[1:]防止&符號重複; percentEncode(“/”) -> %2F
stringToSign
‘GET&%2F&Format%3DJSON%26SignatureMethod%3DHMAC-SHA1%26Version%3D2014-05-26‘ #注意,這裡除GET外,其他引數需要按照ASCII碼排序

3計算 HMAC 值

access_key_secret = ‘access_key_secret‘
h = hmac.new(access_key_secret + "&",stringToSign,sha1) # 標準要求加密用的金鑰是"原金鑰+&"作為加密的key
h
<hmac.HMAC instance at 0x35ed440>

4計算簽名值

signature = base64.encodestring(h.digest()).strip()
signature
‘sq8LVH+ZItZiVQ0/rVnHV1kP/BE=‘
到此生成了 signature 簽名

5添加簽名

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 後直接訪問就可以得到結果。

最終簽名程式

python3.6版本(1為寫死的方式,2為配置檔案及命令列方式)
1寫死金鑰與呼叫固定API DescribeInstancesRequest-api-py3.py

!/usr/bin/env python

-- coding:utf-8 --

"""

File Name: DescribeInstancesRequest-api-py3.py
Description:
Author: chenxin
date: 2018/11/19 18:10

"""

該指令碼適用於python3.x版本

import sys
import urllib.parse
import urllib.request
import base64
import hmac
from hashlib import sha1
import time
import uuid

access_key_id = ‘LTAI3b9Wpey0U0cc‘
access_key_secret = ‘kFV8tfHBKesPC1gMnglbxAdEygPys2‘

定義endpoint終端節點地址(服務節點)

handle_server_address = ‘https://ecs.aliyuncs.com

對 URL 進行編碼

def percent_encode(string):
res = urllib.parse.quote(string.encode(sys.stdin.encoding,‘utf8‘),‘~‘)
return res

計算簽名

def compute_signature(parameters,access_key_secret2):
# 先排序,生成一個list.簽名值是根據所有引數ascii值排序後生成的字串計算來的.
sorted_parameters = sorted(parameters.items(),key=lambda x: x[0])
# 生成規範化的請求字串canonicalized_query_string.
canonicalized_query_string = ‘‘
for (k,v) in sorted_parameters:
canonicalized_query_string += ‘&‘ + percent_encode(k) + ‘=‘ + percent_encode(v)
# 構造待簽名字串 string_to_sign.這裡從[1:]開始,因為從0開始,會變成GET&%2F&&Action=...多了一個"&"符號
string_to_sign = ‘GET&%2F&‘ + percent_encode(canonicalized_query_string[1:])
# 計算簽名時,RFC2104規定的Key值是你的 AccessKeySecret 並加上與號&,其ASCII值為38.
# python3直接使用str模式的話,會報TypeError: key: expected bytes or bytearray,but got ‘str‘錯誤.故先轉換為bytes.
access_key_secret_bytes = bytes(access_key_secret2,‘utf-8‘)
and_sign_bytes = bytes("&",‘utf-8‘)
string_to_sign_bytes = bytes(string_to_sign,‘utf-8‘)
h = hmac.new(access_key_secret_bytes + and_sign_bytes,string_to_sign_bytes,sha1)
signature = base64.encodebytes(h.digest()).strip()
return signature

構造整體url地址

def compose_url():
timestamp = time.strftime("%Y-%m-%dT%H:%M:%SZ",time.gmtime())
parameters = {
‘Format‘: ‘JSON‘,
‘Version‘: ‘2014-05-26‘,
‘AccessKeyId‘: access_key_id,
‘SignatureVersion‘: ‘1.0‘,
‘SignatureNonce‘: str(uuid.uuid1()),
‘TimeStamp‘: timestamp,
‘Action‘: ‘DescribeInstances‘,# 介面引數
‘RegionId‘: ‘cn-shenzhen‘,# 介面引數
}
# 計算簽名.引數access_key_secret是個全域性引數
signature = compute_signature(parameters,access_key_secret)
# 將簽名引數植入parameters字典
parameters[‘Signature‘] = signature
# 構造最終訪問url地址.當前parameters字典裡包含了公共請求引數+介面引數+簽名
url = handle_server_address + "/?" + urllib.parse.urlencode(parameters)
return url

if name == ‘main‘:
# 獲取URL地址
url_address = compose_url()
print(url_address)
# 訪問API介面,並返回相關結果
return_info = urllib.request.urlopen(url_address).read()
# 解決中文亂碼
return_info_utf8 = return_info.decode(‘UTF-8‘)
print(return_info_utf8)

2帶金鑰配置檔案與命令呼叫(對應服務API)方式 signature-auth-py3.py

!/usr/bin/env python

-- coding:utf-8 --

"""

File Name: signature_auth_py3.py
Description:
Author: chenxin
date: 2018/11/22 10:59

"""

使用方法:

1把accesskey+accesssecet放到aliyun.ini

2執行python xxx.py Action=xxx B=yyy C=zzz

3其他介面都一樣,看一下文件,傳引數即可

python signature_auth.py DescribeInstances RegionId=cn-shenzhen

python signature_auth.py Action=DescribeInstances RegionId=cn-shenzhen

python signature_auth.py Action=DescribeInstanceStatus RegionId=cn-shenzhen

import sys
import os
import urllib.parse
import urllib.request
import base64
import hmac
from hashlib import sha1
import time
import uuid
from optparse import OptionParser
import configparser
import traceback

公共變數

access_key_id = ‘‘
access_key_secret = ‘‘

定義終端節點地址(服務節點)

handle_server_address = ‘https://ecs.aliyuncs.com

配置檔案,非windows系統為‘/aliyun.ini‘

CONFIGFILE = os.getcwd() + ‘\aliyun.ini‘

[Credentials] 是配置檔案中的一個章節

CONFIGSECTION = ‘Credentials‘
cmdlist = ‘‘‘介面說明請參考線上文件‘‘‘

對 URL 進行編碼

def percent_encode(str):
res = urllib.parse.quote(str.encode(sys.stdin.encoding,‘~‘)
return res

計算簽名

def compute_signature(parameters,access_key_secret):
# 先排序,key=lambda parameters: parameters[0])
# 生成規範化的請求字串canonicalized_query_string.
canonicalized_query_string = ‘‘
for (k,but got ‘str‘錯誤.故先轉換為bytes.
access_key_secret_bytes = bytes(access_key_secret,sha1)
signature = base64.encodebytes(h.digest()).strip()
# python2.7使用以下.
# h = hmac.new(access_key_secret + "&",string_to_sign,sha1)
# signature = base64.encodestring(h.digest()).strip()
return signature

構造整體url地址

def compose_url(user_params):
timestamp = time.strftime("%Y-%m-%dT%H:%M:%SZ",
}
# 將使用者手動輸入的引數裝入parameters字典.這樣parameters中儲存著所有引數(含公共引數,介面引數,暫時不含簽名引數)
for key in user_params.keys():
parameters[key] = user_params[key]
# 計算簽名.引數access_key_secret是個全域性引數
signature = compute_signature(parameters,access_key_secret)
# 將簽名引數植入parameters字典
parameters[‘Signature‘] = signature
# 構造最終訪問url地址.當前parameters字典裡包含了公共請求引數+介面引數+簽名
url = handle_server_address + "/?" + urllib.parse.urlencode(parameters)
return url

xxx.py呼叫命令中含金鑰配置檔案的路徑的話(自定義路徑),執行寫入操作

def configure_accesskeypair(args,options):
if options.accesskeyid is None or options.accesskeysecret is None:
print("config miss parameters,use --id=[accesskeyid] --secret=[accesskeysecret]")
sys.exit(1)
config = configparser.RawConfigParser()
config.add_section(CONFIGSECTION)
config.set(CONFIGSECTION,‘accesskeyid‘,options.accesskeyid)
config.set(CONFIGSECTION,‘accesskeysecret‘,options.accesskeysecret)
cfgfile = open(CONFIGFILE,‘w+‘)
config.write(cfgfile)
cfgfile.close()

xxx.py 呼叫命令中第一個引數不是金鑰配置路徑的話,則執行預設的認證步驟,如下

def setup_credentials():
config = configparser.ConfigParser()
try:
# 讀取配置檔案
config.read(CONFIGFILE)
global access_key_id
global access_key_secret
# 獲取CONFIGSECTION章節中對應的欄位
access_key_id = config.get(CONFIGSECTION,‘accesskeyid‘)
access_key_secret = config.get(CONFIGSECTION,‘accesskeysecret‘)
except Exception as e:
print(traceback.format_exc())
print(e)
print("can‘t get access key pair,use config --id=[accesskeyid] --secret=[accesskeysecret] to setup")
sys.exit(1)

if name == ‘main‘:
# 製作幫助資訊
parser = OptionParser("%s Action=action Param1=Value1 Param2=Value2\n" % sys.argv[0])
parser.add_option("-i","--id",dest="accesskeyid",help="specify access key id")
parser.add_option("-s","--secret",dest="accesskeysecret",help="specify access key secret")
(options,args) = parser.parse_args()
if len(args) < 1:
parser.print_help()
sys.exit(0)
if args[0] == ‘help‘:
print(cmdlist)
sys.exit(0)
if args[0] != ‘config‘:
setup_credentials()
else:
configure_accesskeypair(args,options)
sys.exit(0)
user_params = {} # 用來儲存使用者手動呼叫時給出的引數
idx = 1
# 如果第一個引數不是以Action=開頭的話,則將第一個引數全部賦值給user_params[‘action‘],以便適應python signature_auth.py DescribeInstanceStatus方式呼叫.
# 這裡Action,RegionId等,可以全部小寫的,URL呼叫中不敏感.
if not sys.argv[1].lower().startswith(‘action=‘):
user_params[‘action‘] = sys.argv[1]
idx = 2
for arg in sys.argv[idx:]:
try:
key,value = arg.split(‘=‘)
user_params[key.strip()] = value # .strip()預設刪除空白符(包括‘\n‘,‘\r‘,‘\t‘,‘ ‘)
except ValueError as e:
# print(e.read().strip())
print(e)
raise SystemExit(e)
# 獲取最終訪問URL地址
url_address = compose_url(user_params)
print(url_address)
return_info = urllib.request.urlopen(url_address).read()
# 因當前使用的是windows控制檯呼叫的python,所以需要匹配系統編碼.否則阿里雲返回的中文資訊會亂碼.
type = sys.getfilesystemencoding()
return_info_gbk = return_info.decode(‘UTF-8‘)
print(return_info_gbk)

python2.7版本
signature-auth-py2.py

!/usr/bin/python

-- coding:utf-8 --

"""

File Name:
Description:
Author: chenxin
date: 2018/11/21 17:56

"""

使用方法:

1把accesskey+accesssecet放到aliyun.ini

2執行python xxx.py Action=xxx B=yyy C=zzz

3其他介面都一樣,傳引數即可

python signature_auth.py DescribeInstances RegionId=cn-shenzhen

python signature_auth.py Action=DescribeInstances RegionId=cn-shenzhen

python signature_auth.py Action=DescribeInstanceStatus RegionId=cn-shenzhen

import sys,os
import urllib,urllib2
import base64
import hmac
import hashlib
from hashlib import sha1
import time
import uuid
import json
from optparse import OptionParser
import ConfigParser
import traceback

access_key_id = ‘‘;
access_key_secret = ‘‘;

cdn_server_address = ‘https://cdn.aliyuncs.com

cdn_server_address = ‘https://ecs.aliyuncs.com
CONFIGFILE = os.getcwd() + ‘\aliyun.ini‘
CONFIGSECTION = ‘Credentials‘
cmdlist = ‘‘‘介面說明請參照pdf文件‘‘‘

將 URL 進行編碼

def percent_encode(str):
res = urllib.quote(str.decode(sys.stdin.encoding).encode(‘utf8‘),‘~‘)
return res

計算簽名

def compute_signature(parameters,access_key_secret):
#先排序,生成一個list.簽名值是根據所有引數ascii值排序後生成的字串計算來的.
sortedParameters = sorted(parameters.items(),key=lambda parameters: parameters[0])
#生成規範化的請求字串canonicalizedQueryString.
canonicalizedQueryString = ‘‘
for (k,v) in sortedParameters:
canonicalizedQueryString += ‘&‘ + percent_encode(k) + ‘=‘ + percent_encode(v)
#構造待簽名字串 StringToSign.這裡從[1:]開始,會變成GET&%2F&&Action=...多了一個"&"符號
stringToSign = ‘GET&%2F&‘ + percent_encode(canonicalizedQueryString[1:])
#計算簽名時,其ASCII值為38.
h = hmac.new(access_key_secret + "&",sha1)
signature = base64.encodestring(h.digest()).strip()
return signature

def compose_url(user_params):
timestamp = time.strftime("%Y-%m-%dT%H:%M:%SZ",time.gmtime())

parameters = {
    ‘Format‘: ‘JSON‘,‘Version‘: ‘2014-05-26‘,‘AccessKeyId‘: access_key_id,‘SignatureVersion‘: ‘1.0‘,‘SignatureMethod‘: ‘HMAC-SHA1‘,‘SignatureNonce‘: str(uuid.uuid1()),‘TimeStamp‘: timestamp,}

#將使用者手動輸入的引數裝入parameters字典.這樣parameters中儲存著所有引數(含公共引數,暫時不含簽名引數)
for key in user_params.keys():
    parameters[key] = user_params[key]
#計算簽名.引數access_key_secret是個全域性引數
signature = compute_signature(parameters,access_key_secret)
#將簽名引數植入parameters字典
parameters[‘Signature‘] = signature
#構造最終訪問url地址.當前parameters字典裡包含了公共請求引數+介面引數+簽名
url = cdn_server_address + "/?" + urllib.urlencode(parameters)
return url

def make_request(user_params,quiet=False):
url = compose_url(user_params)
# print url
return url

def configure_accesskeypair(args,use --id=[accesskeyid] --secret=[accesskeysecret]")
sys.exit(1)
config = ConfigParser.RawConfigParser()
config.add_section(CONFIGSECTION)
config.set(CONFIGSECTION,‘w+‘)
config.write(cfgfile)
cfgfile.close()

def setup_credentials():
config = ConfigParser.ConfigParser()
try:
config.read(CONFIGFILE)
global access_key_id
global access_key_secret
access_key_id = config.get(CONFIGSECTION,‘accesskeysecret‘)
except Exception,e:
print traceback.format_exc()
print("can‘t get access key pair,use config --id=[accesskeyid] --secret=[accesskeysecret] to setup")
sys.exit(1)

if name == ‘main‘:
#製作-h --help資訊
parser = OptionParser("%s Action=action Param1=Value1 Param2=Value2\n" % sys.argv[0])
parser.add_option("-i",args) = parser.parse_args()
if len(args) < 1:
parser.print_help()
sys.exit(0)

if args[0] == ‘help‘:
    print cmdlist
    sys.exit(0)
if args[0] != ‘config‘:
    setup_credentials()
else:  # it‘s a configure id/secret command
    configure_accesskeypair(args,options)
    sys.exit(0)

user_params = {}    #用來儲存使用者手動呼叫時給出的引數
idx = 1

#如果第一個引數不是以Action=開頭的話,以便適應python signature.py DescribeInstanceStatus方式呼叫.
#這裡Action,URL呼叫中不敏感.
if not sys.argv[1].lower().startswith(‘action=‘):
    user_params[‘action‘] = sys.argv[1]
    idx = 2

for arg in sys.argv[idx:]:
    try:
        key,value = arg.split(‘=‘)
        user_params[key.strip()] = value    #.strip()預設刪除空白符(包括‘\n‘,‘ ‘)
    except ValueError,e:
        print(e.read().strip())
        raise SystemExit(e)
# 獲取最終訪問URL地址
url_address = make_request(user_params)
return_info = urllib.urlopen(url_address).read()
# 因當前使用的是windows控制檯呼叫的python,所以需要匹配系統編碼.否則阿里雲返回的中文資訊會亂碼.
type = sys.getfilesystemencoding()
return_info_gbk = return_info.decode(‘UTF-8‘).encode(type)
print return_info_gbk

補充知識
HMAC說明

HMAC的一個典型應用是用在“質疑/應答”(Challenge/Response)身份認證中。
認證流程
(1) 先由客戶端向伺服器發出一個驗證請求。
(2) 伺服器接到此請求後生成一個隨機數並通過網路傳輸給客戶端(此為質疑)。
(3) 客戶端將收到的隨機數提供給ePass,由ePass使用該隨機數與儲存在ePass中的金鑰進行HMAC-MD5運算並得到一個結果作為認證證據傳給伺服器(此為響應)。
(4) 與此同時,伺服器也使用該隨機數與儲存在伺服器資料庫中的該客戶金鑰進行HMAC-MD5運算,如果伺服器的運算結果與客戶端傳回的響應結果相同,則認為客戶端是一個合法使用者

在這個過程中,可能遭到安全攻擊的是伺服器傳送的隨機值和使用者傳送的hmac結果,而對於截獲了這兩個值的黑客而言這兩個值是沒有意義的,絕無獲取使用者密碼的可能性,隨機值的引入使hmac只在當前會話中有效,大大增強了安全性和實用性。