後端簽名密鑰是由您建立的一對 Key 和 Secret,相當於您給API Gateway頒發了一個帳號密碼。API綁定後端簽名外掛程式後 ,API Gateway向您後端服務要求時會使用這一對Key和Secret對請求內容進行加簽處理,您後端服務可以對網關發送過來的請求做對稱加簽計算,對比網關的簽名和伺服器端計算的簽名是否一致就可以對網關做身分識別驗證。
1. 什麼是後端簽名
後端簽名(原名:簽名密鑰)是由您建立的一對 Key 和 Secret,相當於您給網關頒發了一個帳號密碼,網關向您後端服務要求時會將密鑰計算後一起傳過去,您後端擷取相應的字串做對稱計算,就可以對網關做身分識別驗證。若您的後端服務為VPC環境,且通過內網對接(專屬網路VPC環境開放API),您無需使用後端簽名,通道自身是安全的。
原簽名密鑰功能現在合并進了外掛程式體系。現存的控制台介面與介面仍然可以使用,原簽名密鑰功能與後端簽名外掛程式屬於同一種外掛程式類型,受到同類型外掛程式綁定的限制。
使用原簽名密鑰功能介面或控制台建立或更改,會同步資料至外掛程式系統,但不會反向同步。
2. 外掛程式綁定
您將密鑰綁定到 API 之後,由網關發送給您服務後端的該 API 的請求均會加上籤名資訊。您需要在後端做對稱計算來解析簽名資訊,從而驗證網關的身份。
當您想替換某個API的密鑰時,請直接修改要修改外掛程式中的key和secret, 已綁定的API將會即時生效。
3. 外掛程式配置
可以選擇JSON或者YAML格式的來配置您的外掛程式,兩種格式的schema相同,可以搜尋yaml to json轉換工具來進行配置格式的轉換,YAML格式的模板見下表
---
type: APIGW_BACKEND
key: SampleKey
secret: SampleSecret
4. 讀取 API Gateway簽名方法
網關計算的簽名儲存在 Request 的 Header 中,Header 名稱:X-Ca-Proxy-Signature。
5. 後端簽名規則
簽名計算的詳細 demo(JAVA)請參照連結:https://github.com/aliyun/api-gateway-demo-sign-backend-java。
簽名計算方法步驟如下:
API Gateway需要從發送給後端的HTTP請求中提取出關鍵資料,組合成一個簽名串,產生的簽名串的格式如下:
HTTPMethod Content-MD5 Headers PathAndParameters
以上4個欄位構成整個簽名串,欄位之間使用\n間隔,如果Headers為空白,則不需要加\n,其他欄位如果為空白都需要保留\n。簽名大小寫敏感。下面介紹下每個欄位的擷取規則:
HTTPMethod:HTTP的方法,全部大寫,比如POST
Content-MD5:網關會從用戶端請求Header中讀取Content-MD5頭的值,如果用戶端不傳這個Content-MD5頭,網關的簽名串的Content-MD5的值為空白。用戶端只有在請求存在Body且Body為非Form形式時才需要計算並且傳輸Content-MD5頭。下面是Java的Content-MD5值的參考計算方式:
String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getbytes("UTF-8")));
Headers:Headers 指所有參與簽名計算的 Header的Key、Value。參與簽名計算的 Header 的 Key 從 Request Header 中讀取,Key為:"X-Ca-Proxy-Signature-Headers",多個 Key 用英文逗號分割。先對所有參與簽名計算的 Header 的 Key 按照字典排序,然後將 Header 的 Key 轉換成小寫後按照如下方式拼接:
String headers = HeaderKey1.toLowerCase() + ":" + HeaderValue1 +"\n"+ HeaderKey2.toLowerCase() + ":" + HeaderValue2 +"\n"+ ... + HeaderKeyN.toLowerCase() + ":" + HeaderValueN + "\n"
PathAndParameters
這個欄位包含Path,Query和Form中的所有參數,組織方法: 如果有 Query 或 Form 參數則加 ?,然後對 Query+Form 參數按照字典對 Key 進行排序後按照如下方法拼接,如果沒有 Query 或 Form 參數,則 PathAndParameters = Path
String PathAndParameters = Path + "?" + Key1 + "=" + Value1 + "&" + Key2 + "=" + Value2 + ... "&" + KeyN + "=" + ValueN
說明 這裡 Query 或 Form 參數的 Value 可能有多個,多個的時候只取第一個 Value 參與簽名計算; 只要傳遞了的參數,簽名過程中的等號“=“無論什麼情況都需要保留,比如這兩個query參數傳遞時的形式:"path?a=&b",簽名時需要寫成:"path?a=&b="。
計算簽名:
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
byte[] keyBytes = secret.getBytes("UTF-8"); //secret 為綁定到 API 上的簽名密鑰
hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, "HmacSHA256"));
String sign = new String(Base64.encodeBase64(Sha256.doFinal(stringToSign.getBytes("UTF-8")),"UTF-8"));
抽象一下就是將串(StringToSign)使用UTF-8解碼後得到Byte數組,然後使用密碼編譯演算法對Byte數組進行加密,然後使用Base64演算法進行編碼,形成最終的簽名。
6. 偵錯模式
為了方便後端簽名接入與調試,可以開啟 Debug 模式進行調試,具體方法如下: 請求API Gateway的 Header 中添加 X-Ca-Request-Mode = debug。
後端服務在 Header 中讀取 X-Ca-Proxy-Signature-String-To-Sign 即可,因為 HTTP Header 中值不允許有分行符號,因此分行符號被替換成了 "#"。
注意:X-Ca-Proxy-Signature-String-To-Sign 不參與後端簽名計算。
7. 時間戳記校正
如果後端需要對請求進行時間戳記校正,可以在 API 定義中選擇系統參數 "CaRequestHandleTime" ,值為網關收到請求的格林威治時間。