簽名機(jī)制
為保證API的安全調(diào)用,在調(diào)用API時(shí)阿里云會(huì)對(duì)每個(gè)API請(qǐng)求通過(guò)簽名(Signature)進(jìn)行身份驗(yàn)證。無(wú)論使用HTTP還是HTTPS協(xié)議提交請(qǐng)求,都需要在請(qǐng)求中包含簽名信息。
概述
RPC API要按以下格式在API請(qǐng)求的Query中增加簽名(Signature)。
https://opt.cn-beijing.aliyuncs.com/
?SignatureVersion=1.0
&Action=GetOpenStatus
&Format=JSON
&SignatureNonce=c0eda6ff-a727-496e-a2bd-d9a7ff4803c11629267192400268
&Version=2021-07-30
&AccessKeyId=LTAI5t9vARPxSjReN7VU****
&Signature=t0wVIEI7kZpOin+o4zhguQ8I****
&SignatureMethod=HMAC-SHA1
&Timestamp=2021-08-18T06:13:12Z
其中:
SignatureMethod:簽名方式,目前支持HMAC-SHA1。
SignatureVersion:簽名算法版本,目前版本是 1.0。
SignatureNonce:唯一隨機(jī)數(shù),用于防止網(wǎng)絡(luò)重放攻擊。用戶(hù)在不同請(qǐng)求間要使用不同的隨機(jī)數(shù)值,建議使用通用唯一識(shí)別碼(Universally Unique Identifier, UUID)。
Signature: 使用AccessKey Secret對(duì)請(qǐng)求進(jìn)行對(duì)稱(chēng)加密后生成的簽名。
簽名算法遵循RFC 2104 HMAC-SHA1規(guī)范,使用AccessSecret對(duì)編碼、排序后的整個(gè)請(qǐng)求串計(jì)算HMAC值作為簽名。簽名的元素是請(qǐng)求自身的一些參數(shù),由于每個(gè)API請(qǐng)求內(nèi)容不同,所以簽名的結(jié)果也不盡相同。可參考本文的操作步驟,計(jì)算簽名值。
Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign)) )
步驟一:構(gòu)造待簽名字符串
使用請(qǐng)求參數(shù)構(gòu)造規(guī)范化的請(qǐng)求字符串(Canonicalized Query String)。
按照參數(shù)名稱(chēng)的字典順序?qū)φ?qǐng)求中所有的請(qǐng)求參數(shù)(包括公共請(qǐng)求參數(shù)和接口的自定義參數(shù),但不包括公共請(qǐng)求參數(shù)中的Signature參數(shù))進(jìn)行排序。
說(shuō)明當(dāng)使用GET方法提交請(qǐng)求時(shí),這些參數(shù)就是請(qǐng)求URI中的參數(shù)部分,即URI中“?”之后由“&”連接的部分。
對(duì)排序之后的請(qǐng)求參數(shù)的名稱(chēng)和值分別用UTF-8字符集進(jìn)行URL編碼。編碼規(guī)則請(qǐng)參考下表。
字符
編碼方式
A-Z、a-z和0-9以及“-”、“_”、“.”和“~”
不編碼。
其它字符
編碼成
%XY
的格式,其中XY
是字符對(duì)應(yīng)ASCII碼的16進(jìn)制表示。例如英文的雙引號(hào)(””)對(duì)應(yīng)的編碼為%22
。擴(kuò)展的UTF-8字符
編碼成
%XY%ZA…
的格式。英文空格
編碼成
%20
,而不是加號(hào)(+)。該編碼方式和一般采用的
application/x-www-form-urlencoded
MIME格式編碼算法(例如Java標(biāo)準(zhǔn)庫(kù)中的java.net.URLEncoder
的實(shí)現(xiàn))存在區(qū)別。編碼時(shí)可以先用標(biāo)準(zhǔn)庫(kù)的方式進(jìn)行編碼,然后把編碼后的字符串中的加號(hào)(+)替換成%20
,星號(hào)(*)替換成%2A
,%7E
替換回波浪號(hào)(~),即可得到上述規(guī)則描述的編碼字符串。本算法可以用下面的percentEncode
方法來(lái)實(shí)現(xiàn):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; }
將編碼后的參數(shù)名稱(chēng)和值用英文等號(hào)(=)進(jìn)行連接。
將等號(hào)連接得到的參數(shù)組合按步驟 a排好的順序依次使用“&”符號(hào)連接,即得到規(guī)范化請(qǐng)求字符串。
將第一步構(gòu)造的規(guī)范化字符串按照下面的規(guī)則構(gòu)造成待簽名的字符串。
StringToSign= HTTPMethod + “&” + percentEncode(“/”) + ”&” + percentEncode(CanonicalizedQueryString)
其中:
HTTPMethod 是提交請(qǐng)求用的HTTP方法,例如GET。
percentEncode(“/”) 是按照步驟1.1中描述的 URL 編碼規(guī)則對(duì)字符 “/” 進(jìn)行編碼得到的值,即 %2F。
percentEncode(CanonicalizedQueryString) 是對(duì)步驟1中構(gòu)造的規(guī)范化請(qǐng)求字符串按步驟 1.b 中描述的URL編碼規(guī)則編碼后得到的字符串。
步驟二:計(jì)算簽名值
按照RFC2104的定義,計(jì)算待簽名字符串(StringToSign)的HMAC值。
說(shuō)明計(jì)算簽名時(shí)使用的Key就是您持有的AccessKey Secret并加上一個(gè) “&” 字符(ASCII:38), 使用的哈希算法是SHA1。
按照Base64編碼規(guī)則把上面的HMAC值編碼成字符串,即得到簽名值(Signature)。
將得到的簽名值作為Signature參數(shù)添加到請(qǐng)求參數(shù)中。
說(shuō)明得到的簽名值在作為最后的請(qǐng)求參數(shù)值提交時(shí)要和其它參數(shù)一樣,按照RFC3986的規(guī)則進(jìn)行URL編碼。
示例
以GetOpenStatus 為例,假設(shè)使用的AccessKey Id
為 testid
, AccessKey Secret
為testsecret
。 簽名前的請(qǐng)求URL如下:
https://opt.cn-beijing.aliyuncs.com/?SignatureVersion=1.0&Action=GetOpenStatus&Format=JSON&SignatureNonce=ed8fb51f-0c38-4da4-a21a-f189b3a7aecb1629267396181268&Version=2021-07-30&AccessKeyId=testid&SignatureMethod=HMAC-SHA1&Timestamp=2021-08-18T06:16:36Z
使用testsecret&
,計(jì)算得到的簽名值是:
PPwfMBfMXQlG1RqZFp6B/oxl3n4
最后將簽名作為Signature參數(shù)加入到URL請(qǐng)求中,最后得到的URL為:
https://opt.cn-beijing.aliyuncs.com/?SignatureVersion=1.0&Action=GetOpenStatus&Format=JSON&SignatureNonce=ed8fb51f-0c38-4da4-a21a-f189b3a7aecb1629267396181268&Version=2021-07-30&AccessKeyId=testid&Signature=PPwfMBfMXQlG1RqZFp6B/oxl3n4=&SignatureMethod=HMAC-SHA1&Timestamp=2021-08-18T06:16:36Z