移動網關提供服務端 HTTP 服務簽名驗證功能,提高從網關到服務端的資料安全性。
在網關控制台開啟某一 API 分組的簽名校正後,移動網關會對該分組裡面的每一個 API 請求建立簽名資訊,簽名使用的公私密金鑰可在網關控制台建立。
服務端讀取簽名字串後,對收到的請求進行本地簽名計算,比對與收到的簽名是否一致,以此來判斷請求是否合法。
讀取簽名
移動網關計算的簽名儲存在 Request 的 Header 中,Header Key 為 X-Mgs-Proxy-Signature。
API 分組中配置的密鑰 Key 可用來區分和擷取不同的密鑰值對應的 Key,Header Key 為 X-Mgs-Proxy-Signature-Secret-Key。
驗簽方法
組織加簽資料
String stringToSign =
HTTPMethod + "\n" +
Content-MD5 + "\n" +
UrlHTTPMethod:全大寫的 HTTPMethod,如PUT或POST等。Content-MD5:請求 Body 的 MD5 值。計算方法如下:若
HTTPMethod不是 PUT 或 POST 之一,則 MD5 為空白字串"";否則執行第二步。若請求有 Body 且 Body 為 Form 表單,則 MD5 為空白字串
"";否則執行第三步。使用以下方式計算 MD5。其中,當請求無 Body 時,
bodyStream為字串"null"。String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getbytes(“UTF-8”)));重要即使
content-MD5為空白字串"",加簽方法中content-MD5後面的分行符號 “\n” 也不能省略,即此時簽名中會有連續兩個 “\n”。
Url:由 Path、Query 以及 Body 中的 Form 參數組裝而成。假設請求格式為http://ip:port/test/testSign?c=3&a=1且 Form 中的參數為b=2&d=4,組裝步驟如下:擷取 Path:Path 是
ip:port之後、?之前的部分。此例中即為/test/testSign。若請求 Query 和 Form 參數均為空白,則
Url即為 Path;否則進行下一步。拼接參數。將 Query 和 Form 中的參數根據 Key 按照字典序排序,然後拼接為
Key1=Value1&Key2=Value2&...&KeyN=ValueN。此例中即為a=1&b=2&c=3&d=4。說明Query 或 Form 參數的 Value 可能有多個,只取第一個
Value即可。拼接 URL。URL 為
Path?Key1=Value1&Key2=Value2&...&KeyN=ValueN。此例中即為/test/testSign?a=1&b=2&c=3&d=4。
驗證簽名
採用 MD5 演算法驗簽
String sign = "xxxxxxx";//移動網關傳過來的簽名 String salt ="xxx"; //MD5 Salt MessageDigest digest = MessageDigest.getInstance("MD5"); String toSignedContent = stringToSign + salt; byte[] content = digest.digest(toSignedContent.getBytes("UTF-8")); String computedSign = new String(Hex.encodeHexString(content)); boolean isSignLegal = sign.equals(computedSign) ? true : false;採用 RSA 演算法驗簽
String sign = "xxxxxxx"; //移動網關傳過來的簽名 String publicKey ="xxx"; //移動網關的 RSA 公開金鑰 PublicKey pubKey = KeyReader.getPublicKeyFromX509("RSA", new ByteArrayInputStream(publicKey.getBytes())); java.security.Signature signature = java.security.Signature.getInstance("SHA1WithRSA"); signature.initVerify(pubKey); signature.update(stringToSign.getBytes("UTF-8")); boolean isSignLegal = signature.verify(Base64.decodeBase64(sign.getBytes(""UTF-8"")));
程式碼範例
更多詳情,請參考 HttpSignUtil.java。