為保證API的安全調用,在調用API時阿里云會對每個API請求通過簽名(Signature)進行身份驗證。無論使用HTTP還是HTTPS協議提交請求,都需要在請求中包含簽名信息。
概述
RPC API要按以下格式在API請求的Query中增加簽名(Signature)。
https://Endpoint/?SignatureVersion=1.0&SignatureMethod=HMAC-SHA1&Signature=CT9X0VtwR86fNWSnsc6v8YGOjuE%3D&SignatureNonce=3ee8c1b8-83d3-44af-a94f-4e0ad82fd6cf
其中:
- SignatureMethod:簽名方式,目前支持HMAC-SHA1。
- SignatureVersion:簽名算法版本,目前版本是1.0。
- SignatureNonce:唯一隨機數,用于防止網絡重放攻擊。用戶在不同請求間要使用不同的隨機數值,建議使用通用唯一識別碼UUID(Universally Unique Identifier)。
- Signature:使用AccessKey Secret對請求進行對稱加密后生成的簽名。
簽名算法遵循RFC 2104 HMAC-SHA1規范,使用AccessKey Secret對編碼、排序后的整個請求串計算HMAC值作為簽名。簽名的元素是請求自身的一些參數,由于每個API請求內容不同,所以簽名的結果也不盡相同。可參考本文的操作步驟,計算簽名值。
Signature = Base64( HMAC-SHA1( AccessKey Secret, UTF-8-Encoding-Of(StringToSign)) )
步驟一:構造待簽名字符串
- 使用請求參數構造規范化的請求字符串(Canonicalized Query String)。
- 按照參數名稱的字典順序對請求中所有的請求參數(包括公共請求參數和接口的自定義參數,但不包括公共請求參數中的Signature參數)進行排序。 說明 當使用GET方法提交請求時,這些參數就是請求URI中的參數部分,即URI中“?”之后由“&”連接的部分。
- 對排序之后的請求參數的名稱和值分別用UTF-8字符集進行URL編碼。編碼規則請參考下表。
字符 編碼方式 A~Z、a~z和0~9以及“-”、“_”、“.”和“~” 不編碼。 其它字符 編碼成 %XY
的格式,其中XY
是字符對應ASCII碼的16進制表示。例如英文的雙引號(")對應的編碼為%22
。擴展的UTF-8字符 編碼成 %XY%ZA…
的格式。英文空格 編碼成 %20
,而不是加號(+)。該編碼方式和一般采用的application/x-www-form-urlencoded
MIME格式編碼算法(例如Java標準庫中的java.net.URLEncoder
的實現)存在區別。編碼時可以先用標準庫的方式進行編碼,然后把編碼后的字符串中的加號(+)替換成%20
,星號(*)替換成%2A
,%7E
替換回波浪號(~),即可得到上述規則描述的編碼字符串。本算法可以用下面的percentEncode
方法來實現:private static final String ENCODING = "UTF-8"; private static String percentEncode(String value) throws UnsupportedEncodingException { return value != null ? URLEncoder.encode(value, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null; }
- 將編碼后的參數名稱和值用英文等號(=)進行連接。
- 將等號連接得到的參數組合按順序依次使用“&”符號連接,即得到規范化請求字符串。
- 按照參數名稱的字典順序對請求中所有的請求參數(包括公共請求參數和接口的自定義參數,但不包括公共請求參數中的Signature參數)進行排序。
- 將構造的規范化字符串按照下面的規則構造成待簽名的字符串。
StringToSign= HTTPMethod + "&" + percentEncode("/") + "&" + percentEncode(CanonicalizedQueryString)
其中:
- HTTPMethod 是提交請求用的HTTP方法,例如GET。
- percentEncode("/") 是按照URL編碼規則對字符“/”進行編碼得到的值,即%2F。
- percentEncode(CanonicalizedQueryString) 是對構造的規范化請求字符串按URL編碼規則編碼后得到的字符串。
步驟二:計算簽名值
- 按照RFC2104的定義,計算待簽名字符串(StringToSign)的HMAC值。 說明 計算簽名時使用的Key就是您持有的AccessKey Secret并加上一個“&”字符(ASCII:38), 使用的哈希算法是SHA1。
- 按照Base64編碼規則把上面的HMAC值編碼成字符串,即得到簽名值(Signature)。
- 將得到的簽名值作為Signature參數添加到請求參數中。 說明 得到的簽名值在作為最后的請求參數值提交時要和其它參數一樣,按照RFC3986的規則進行URL編碼。
示例
以DescribeDiscoveredResource為例,簽名前的請求URL為:
http://config.cn-shanghai.aliyuncs.com/?AccessKeyId=testid&Action=DescribeDiscoveredResource&Format=JSON&Region=cn-shanghai&RegionId=cn-shanghai&ResourceId=i-uf6hm9lnlzsarrc7****&ResourceType=ACS%3A%3AECS%3A%3AInstance&SignatureMethod=HMAC-SHA1&SignatureNonce=b9942750-e6a8-11ea-b411-73ba779dcf0c&SignatureVersion=1.0&Timestamp=2020-08-25T07%3A58%3A13Z&Version=2019-01-08
對應的StringToSign
是:
GET&%2F&AccessKeyId%3Dtestid%26Action%3DDescribeDiscoveredResource%26Format%3DJSON%26Region%3Dcn-shanghai%26RegionId%3Dcn-shanghai%26ResourceId%3Di-uf6hm9lnlzsarrc7****%26ResourceType%3DACS%25253A%25253AECS%25253A%25253AInstance%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3Db9942750-e6a8-11ea-b411-73ba779dcf0c%26SignatureVersion%3D1.0%26Timestamp%3D2020-08-25T07%25253A58%25253A13Z%26Version%3D2019-01-08
例如:AccessKey ID為:testid,AccessKeySecret為:testsecret,則用于計算HMAC的key為:testsecret&。
計算得到的簽名值為:i+JJvbbP6iDAXEUOP6pTnRSCewc=
。
簽名后的請求URL為:
http://config.cn-shanghai.aliyuncs.com/?Signature=i+JJvbbP6iDAXEUOP6pTnRSCewc=&AccessKeyId=testid&Action=DescribeDiscoveredResource&Format=JSON&Region=cn-shanghai&RegionId=cn-shanghai&ResourceId=i-uf6hm9lnlzsarrc7****&ResourceType=ACS%3A%3AECS%3A%3AInstance&SignatureMethod=HMAC-SHA1&SignatureNonce=b9942750-e6a8-11ea-b411-73ba779dcf0c&SignatureVersion=1.0&Timestamp=2020-08-25T07%3A58%3A13Z&Version=2019-01-08