為保證API的安全調用,在調用API時阿里雲會對每個API請求通過簽名(Signature)進行身分識別驗證。無論使用HTTP還是HTTPS協議提交請求,都需要在請求中包含簽名資訊。
簽名演算法
本文介紹Function ComputeAPI簽名步驟,SDK中已經實現了簽名演算法並對API進行簽名,無需您手動計算。具體資訊,請參見SDK列表。
對於每一個請求,Function Compute服務會根據要求標頭部的Authorization
欄位來校正是否合法(設定了HTTP觸發器的允許匿名訪問的函數除外)。用戶端須使用與Function Compute服務端一致的簽名演算法才能通過驗證,對於未包含簽名欄位或者簽名錯誤的請求,Function Compute將會返回HTTP 403
錯誤。
signature = base64(hmac-sha256(HTTP_METHOD + "\n"
+ CONTENT-MD5 + "\n"
+ CONTENT-TYPE + "\n"
+ DATE + "\n"
+ CanonicalizedFCHeaders
+ CanonicalizedResource))
// Authorization欄位介紹
Authorization = "FC " + accessKeyID + ":" + signature
參數說明如下:
HTTP_METHOD
:大寫的HTTP方法,例如PUT、GET、POST、DELETE。CONTENT-MD5
:請求內容資料的MD5值。如果請求的Header中沒有傳Content-MD5,則此處填入空串。CONTENT-TYPE
:請求內容的類型,Function Compute的類型是application/json
。DATE
:此次操作的時間,不可為空,支援時區為GMT的RFC1123格式,例如Mon, 02 Jan 2006 15:04:05 GMT
。重要 用戶端需要保證產生的時間與服務端的時間相差不超過15分鐘,否則函數服務將拒絕此次請求。CanonicalizedFCHeaders
:所有以x-fc-
為首碼的HTTP頭組成的字串。產生方式,請參見CanonicalizedFCHeaders。CanonicalizedResource
:請求的URL的Path,一般是先對收到的Path解碼,再去掉請求的Path裡的Params內容。- Path的結構為:
$api-version/api-path
api-version
:API版本,目前版本為2016-08-15
。api-path
:訪問各個介面的路徑,例如建立Service為/services
,其他Path,請參見API概覽。
- 需要認證的HTTP觸發器與其他請求的
CanonicalizedResource
不同,下面對這兩種情況分別進行介紹。- 需要認證的HTTP觸發器請求:如果有Params,則以斷行符號符
\n
分隔各個參數,Params中的各個參數key-value對按照字母序進行排序。如果沒有Params則以\n
補齊。 例如:// 需要認證的HTTP觸發器的URL的真實Path /2016-08-15/proxy/service-name/func-name/path-with-%20-space/action?x=1&a=2&x=3&with%20space=foo%20bar // URL decode後的結果 /2016-08-15/proxy/service-name/func-name/path-with- -space/action?x=1&a=2&x=3&with space=foo bar // 需要認證的HTTP觸發器的CanonicalizedResource /2016-08-15/proxy/service-name/func-name/path-with- -space/action\na=2\nwith space=foo bar\nx=1\nx=3 // 普通請求的URL的真實Path /2016-08-15/service-name/func-name/path-with-%20-space/action?x=1&a=2&x=3&with%20space=foo%20bar // URL解碼後的結果 /2016-08-15/service-name/func-name/path-with- -space/action?x=1&a=2&x=3&with space=foo bar // 普通請求的CanonicalizedResource /2016-08-15/service-name/func-name/path-with- -space/action
說明 如果Params裡的key對應多個value,即對key-value整體進行排序。 - 普通請求:首先對收到的Path進行URL解碼,普通請求的
CanonicalizedResource
會只取到?
前面的內容,即捨棄傳入的各個Params
。說明 普通請求是除了需要訪問帶認證的HTTP觸發器的請求外的所有請求。
- 需要認證的HTTP觸發器請求:如果有Params,則以斷行符號符
- Path的結構為:
hmac-sha256
:需要以您的AccessKey Secret為Key。您可以通過以下虛擬碼確認簽名的實現方式:
// 構造字串的過程 function composeStringToSign(method, path, headers, queries) { var contentMD5 = headers['content-md5'] || ''; var contentType = headers['content-type'] || ''; var date = headers['date']; var signHeaders = buildCanonicalHeaders(headers, 'x-fc-'); var u = url.parse(path); var pathUnescaped = decodeURIComponent(u.pathname); var str = `${method}\n${contentMD5}\n${contentType}\n${date}\n${signHeaders}${pathUnescaped}`; if (queries) { var params = []; Object.keys(queries).forEach(function (key) { var values = queries[key]; var type = typeof values; if (type === 'string') { params.push(`${key}=${values}`); return; } if (type === 'object' && values instanceof Array) { queries[key].forEach(function (value) { params.push(`${key}=${value}`); }); } }); params.sort(); str += '\n' + params.join('\n'); } return str; } // 使用HMAC-SHA256和Base64計算簽名的過程,其中Source參數為構造出的字串。 function signString(source, secret) { const buff = crypto.createHmac('sha256', secret) .update(source, 'utf8') .digest(); return new Buffer(buff, 'binary').toString('base64'); }
CanonicalizedFCHeaders
完成以下操作,構造阿里雲規範頭,操作步驟如下:
- 將所有以
x-fc-
為首碼的要求標頭的開頭欄位轉換成小寫字母。 - 對於每一個欄位,產生一個子串
${key}:${value}\n
,例如X-Fc-Invocation-Type:Sync
轉換成x-fc-invocation-type:Sync\n
,這些欄位將會按欄位名從小到大排序。${key}
:HTTP頭的名稱。${value}
:HTTP頭的值。
- 將上述產生的子串聯接成一個整串。您可以通過以下虛擬碼確認簽名的實現方式:
// javascript // prefix = 'x-fc-' function buildCanonicalHeaders(headers, prefix) { var list = []; var keys = Object.keys(headers); var fcHeaders = {}; for (var i = 0; i < keys.length; i++) { var key = keys[i]; var lowerKey = key.toLowerCase().trim(); if (lowerKey.startsWith(prefix)) { list.push(lowerKey); fcHeaders[lowerKey] = headers[key]; } } list.sort(); var canonical = ''; for (var _i = 0; _i < list.length; _i++) { var _key = list[_i]; canonical += `${_key}:${fcHeaders[_key]}\n`; } return canonical; }
Authorization
可由上文計算得出的signature構造出來,構造方法如下:Authorization = "FC " + accessKeyID + ":" + signature