對資料安全性要求高的使用者,需要對發佈的 API 進行更高安全性的鑑權方式設定,提供更安全的認證方式,滿足更嚴格的安全要求。
資料服務發佈的 API 支援基於 AK/SK 認證邏輯的摘要簽章認證方式,避免認證資訊和請求資訊在傳輸程式中被截獲和篡改,提升認證安全性。
FineDataLink 發佈的 API 採用 HMAC-SHA256 摘要算法計算簽章,驗籤邏輯為:
請求發起方(計算簽章,並在請求中帶上簽章) ---> 請求接收方(按請求參數計算簽章,並校驗簽章)
使用者已經发布API,同時绑定API至应用,並設定應用認證方式為摘要認證。
根據下列範例程式碼,建立JAVA 檔案:
package kk;import javax.crypto.Mac;import javax.crypto.spec.SecretKeySpec;import java.math.BigInteger;import java.nio.charset.StandardCharsets;import java.security.MessageDigest;import java.util.Base64;import java.util.UUID;public class k { public static void main(String[] args) { //修改為對應的AppSecret String secretKey = "1bbe91b1-a39c-4742-9694-e126bcf9a3bd"; //請求方式,注意大寫 String httpMethod = "POST"; //POST請求需要寫contentType,GET請求此處寫空字串 String contentType = "application/json"; //API路徑。如果是get請求,需要帶上參數,例如xxx/xxx?a=1 String pathAndParameters = "a5ce6bb4-467b-46f2-8878-2132635973bb/87"; //body請求體的內容 String data = "{\"paging\":{\"pageSize\":10,\"pageNum\":1},\"params\":[]}"; //Nonce,自動生成 String nonce = String.valueOf(UUID.randomUUID()); //時間戳,自動生成 String timestamp = String.valueOf(System.currentTimeMillis()); //待簽章字串 String stringToSign = httpMethod +"\n"+ nonce +"\n"+ timestamp +"\n"+ pathAndParameters +"\n"+ contentType +"\n"+ md5(data); //簽章 String signature = hmacSHA256(secretKey,stringToSign); //拼出完整的Authorization System.out.println("Authorization:\n"+"HMAC-SHA256 Signature="+signature+",Nonce="+nonce+",Timestamp="+timestamp); } /** * 對字串data進行HmacSHA256簽章,以Base64的結果傳回 * * @param secretKey 簽章金鑰 * @param data 待簽章字串 */ public static String hmacSHA256(String secretKey, String data) { try { Mac hmacSha256 = Mac.getInstance("HmacSHA256"); SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); hmacSha256.init(secretKeySpec); byte[] hashBytes = hmacSha256.doFinal(data.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(hashBytes); } catch (Exception e) { throw new RuntimeException("HmacSha error", e); } } /** * 對字串data計算md5摘要值,再進行Base64編碼,傳回編碼後的結果 * * @param data 待計算的字串 */ public static String md5(String data) { try { MessageDigest md = MessageDigest.getInstance("MD5"); md.reset(); md.update(data.getBytes(StandardCharsets.UTF_8)); String md5Result = String.format("%032x", new BigInteger(1, md.digest())); return Base64.getEncoder().encodeToString(md5Result.getBytes(StandardCharsets.UTF_8)); } catch (Exception e) { throw new RuntimeException("md5 error", e); } }}
package kk;import javax.crypto.Mac;import javax.crypto.spec.SecretKeySpec;import java.math.BigInteger;import java.nio.charset.StandardCharsets;import java.security.MessageDigest;import java.util.Base64;import java.util.UUID;public class k { public static void main(String[] args) { //修改為對應的AppSecret String secretKey = "a07eefc1-4b29-469a-8cb1-f68e3532d3a2"; //請求方式,注意大寫 String httpMethod = "GET"; //POST請求需要寫contentType,GET請求此處寫空字串 String contentType = ""; //API路徑。如果是get請求,需要帶上參數,例如xxx/xxx?a=1 String pathAndParameters = "a5ce6bb4-467b-46f2-8878-2132635973bb/dd?pageSize=10&pageNum=1"; //body請求體的內容 String data = ""; //Nonce,自動生成 String nonce = String.valueOf(UUID.randomUUID()); //時間戳,自動生成 String timestamp = String.valueOf(System.currentTimeMillis()); //待簽章字串 String stringToSign = httpMethod +"\n"+ nonce +"\n"+ timestamp +"\n"+ pathAndParameters +"\n"+ contentType +"\n"+ ("".equals(data)?"":md5(data)); //簽章 String signature = hmacSHA256(secretKey,stringToSign); //拼出完整的Authorization System.out.println("Authorization:\n"+"HMAC-SHA256 Signature="+signature+",Nonce="+nonce+",Timestamp="+timestamp); } /** * 對字串data進行HmacSHA256簽章,以Base64的結果傳回 * * @param secretKey 簽章金鑰 * @param data 待簽章字串 */ public static String hmacSHA256(String secretKey, String data) { try { Mac hmacSha256 = Mac.getInstance("HmacSHA256"); SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); hmacSha256.init(secretKeySpec); byte[] hashBytes = hmacSha256.doFinal(data.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(hashBytes); } catch (Exception e) { throw new RuntimeException("HmacSha error", e); } } /** * 對字串data計算md5摘要值,再進行Base64編碼,傳回編碼後的結果 * * @param data 待計算的字串 */ public static String md5(String data) { try { MessageDigest md = MessageDigest.getInstance("MD5"); md.reset(); md.update(data.getBytes(StandardCharsets.UTF_8)); String md5Result = String.format("%032x", new BigInteger(1, md.digest())); return Base64.getEncoder().encodeToString(md5Result.getBytes(StandardCharsets.UTF_8)); } catch (Exception e) { throw new RuntimeException("md5 error", e); } }}
package kk;import javax.crypto.Mac;import javax.crypto.spec.SecretKeySpec;import java.math.BigInteger;import java.nio.charset.StandardCharsets;import java.security.MessageDigest;import java.util.Base64;import java.util.UUID;public class k { public static void main(String[] args) { //修改為對應的AppSecret String secretKey = "1bbe91b1-a39c-4742-9694-e126bcf9a3bd"; //請求方式,注意大寫 String httpMethod = "POST"; //POST請求需要寫contentType,GET請求此處寫空字串 String contentType = "application/x-www-form-urlencoded"; //API路徑。如果是get請求,需要帶上參數,例如xxx/xxx?a=1 String pathAndParameters = "a5ce6bb4-467b-46f2-8878-2132635973bb/87"; //body請求體的內容 body裏的鍵值對也要編碼 String data = "a=1&b=%E6%8C%AA%E5%A8%81"; //Nonce,自動生成 String nonce = String.valueOf(UUID.randomUUID()); //時間戳,自動生成 String timestamp = String.valueOf(System.currentTimeMillis()); //待簽章字串 String stringToSign = httpMethod +"\n"+ nonce +"\n"+ timestamp +"\n"+ pathAndParameters +"\n"+ contentType +"\n"+ md5(data); //簽章 String signature = hmacSHA256(secretKey,stringToSign); //拼出完整的Authorization System.out.println("Authorization:\n"+"HMAC-SHA256 Signature="+signature+",Nonce="+nonce+",Timestamp="+timestamp); } /** * 對字串data進行HmacSHA256簽章,以Base64的結果傳回 * * @param secretKey 簽章金鑰 * @param data 待簽章字串 */ public static String hmacSHA256(String secretKey, String data) { try { Mac hmacSha256 = Mac.getInstance("HmacSHA256"); SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); hmacSha256.init(secretKeySpec); byte[] hashBytes = hmacSha256.doFinal(data.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(hashBytes); } catch (Exception e) { throw new RuntimeException("HmacSha error", e); } } /** * 對字串data計算md5摘要值,再進行Base64編碼,傳回編碼後的結果 * * @param data 待計算的字串 */ public static String md5(String data) { try { MessageDigest md = MessageDigest.getInstance("MD5"); md.reset(); md.update(data.getBytes(StandardCharsets.UTF_8)); String md5Result = String.format("%032x", new BigInteger(1, md.digest())); return Base64.getEncoder().encodeToString(md5Result.getBytes(StandardCharsets.UTF_8)); } catch (Exception e) { throw new RuntimeException("md5 error", e); } }}
用戶端需要傳入 Authorization 請求頭和 Content-Type 頭,使用 GET/POST 向服務端發起請求:
算法名稱:Signature=Signature值, Nonce=Nonce隨機數, Timestamp=Timestamp時間戳
舉例:
HMAC-SHA256 Signature=FiXSVh+oBzitw+HDypwlmB0PE+Z67pdXbQM7QyHA7qk=, Nonce=c967a237-cd6c-470e-906f-a8655461897, Timestamp=1686542039670
根據請求的內容類型,填入Content-Type請求頭內容。
如果是GET請求頭不需要傳入 Content-Type。
其中生成 Signature 值作為「待簽章字串」需要的專案如下,其中標註字母的內容需要使用者根據自己的實際值進行取代:
應用金鑰
在資料服務>應用列表,選擇摘要簽章,即複製 AppSecret,如下圖所示:
請求方法,目前支援傳入GET和POST。注:需要大寫。
驗證時,服務端將會透過此 UUID 檢查近 5 分鐘內是否有重複請求,如果有重複請求,將進行攔截
13 位時間戳(1970-01-01 00:00:00開始到現在的毫秒數),在生成簽章的 Java 程式碼中自動生成
驗證時,服務端將會透過此時間戳,檢查此請求是否已過期,如果請求已過期,將進行攔截
API 配置頁面配置的 API 路徑
如果是 get 請求,需要帶上參數,例如xxx/xxx?a=1
範例:http://192.168.5.175:8089/webroot/service/publish/<appid>/api01?a=1&b=2中的粗體部分,不包含首尾的斜槓
在 API 列表下的授權應用中複製 API 路徑,如下圖所示:
BODY 的 MIME 類型
POST 請求需要寫 contentType,GET 請求此處寫空字串
POST 請求時,在 BODY 中的參數字串
對於json:原樣所有字串,包含空格、回車等符號
對於x-www-form-urlencoded:將鍵值對分別進行 URL 轉碼,然後使用&連結起來;有鍵無值、有值無鍵時正常保留等號
例如 JSON 格式的 Body,範例為:
{"paging":{"pageSize":10,"pageNum":1},"params":[]}
對於以上請求體內容,先做 MD5 處理(匯出32位小寫字串),結果再進行 BASE64 編碼,得到最終的 Content-MD5 結果。
「待簽章字串」構建方式:
待簽章字串 = 「HTTPMethod」+ "\n"
+「Nonce」+ "\n"
+「Timestamp」+ "\n"
+「PathAndParameters」+ "\n"
+「Content-Type」+ "\n"
+「Content-MD5」
注1:加號代表連接,實際是每個專案之間透過換行分隔,如果沒有對應專案,則對應內容用空字串代替,但是換行需要儲存
注2:如果沒有 BODY,那麼 Content-MD5 專案直接為空字串,不對空 BODY 做 MD5(也就是說,目前對於 GET 請求,Content-Type 和 Content-MD5 專案都會為空字串)
待簽章字串生成 Signature 簽章,使用 HMAC-SHA256 加密算法。
Mac hmacSha256 = Mac.getInstance("HmacSHA256");byte[] appSecretBytes = appSecret.getBytes(Charset.forName("UTF-8"));hmacSha256.init(new SecretKeySpec(appSecretBytes, 0, appSecretBytes.length, "HmacSHA256"));byte[] md5Result = hmacSha256.doFinal(stringToSign.getBytes(Charset.forName("UTF-8")));String signature = Base64.encodeBase64String(md5Result);
計算簽章方式同用戶端
校驗專案:
參考本文 3.1 節修改程式碼中的指定內容:
例如使用者已經在 FineDataLink 中發佈請求為 POST application/json 的 API ,則需要準備以下資料,以備生成待簽章字串:
請求方法,目前支援傳入 GET 和 POST注:需要大寫
BODY 的 MIME 類型。
POST請求時,在B ODY 中的參數字串。
對於 json:原樣所有字串,包含空格、回車等符號
對於 x-www-form-urlencoded:將鍵值對分別進行 URL 轉碼,然後使用&連結起來;有鍵無值、有值無鍵時正常保留等號
對於 json 格式的 Body,可在 API 生成介面複製 Body 值
對於以上請求體內容,先做 MD5 處理(匯出32位小寫字串),結果再進行 BASE64 編碼,得到最終的 Content-MD5 結果
然後運作 JAVA 檔案,即可獲得 Authorization ,如下圖所示:
此處以 POST JSON 請求為例,輸入 Authorization 認證和 Body 請求值,即可取出發佈的 API 資料,如下圖所示:
滑鼠選中內容,快速回饋問題
滑鼠選中存在疑惑的內容,即可快速回饋問題,我們將會跟進處理。
不再提示
10s後關閉
反馈已提交
网络繁忙