Nonce 防重缓存同步由 5 分钟延长至 10 分钟
Timestamp 校验范围调整为:与服务端当前时间相比,前/后 5 min以内
對資料安全性要求高的使用者,需要對發佈的 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。注:需要大写。
4.2.21.4 及之后版本,Nonce 防重缓存同步由 5 分钟延长至 10 分钟
UUID,在生成签名的 Java 代码中自动生成。
验证时,服务端将会通过此 UUID 检查近 10 分钟内是否有重复请求,如果有重复请求,将进行拦截
4.2.21.4 及之后版本,校验范围由「服务器当前时间向前 5 分钟」调整为「服务器当前时间前后各 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 ,則需要準備以下資料,以備生成待簽章字串:
應用金鑰
在資料服務>應用列表,選擇摘要簽章,即複製 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請求時,在B ODY 中的參數字串。
對於 json:原樣所有字串,包含空格、回車等符號
對於 x-www-form-urlencoded:將鍵值對分別進行 URL 轉碼,然後使用&連結起來;有鍵無值、有值無鍵時正常保留等號
例如 JSON 格式的 Body,範例為:
對於 json 格式的 Body,可在 API 生成介面複製 Body 值
對於以上請求體內容,先做 MD5 處理(匯出32位小寫字串),結果再進行 BASE64 編碼,得到最終的 Content-MD5 結果
然後運作 JAVA 檔案,即可獲得 Authorization ,如下圖所示:
此處以 POST JSON 請求為例,輸入 Authorization 認證和 Body 請求值,即可取出發佈的 API 資料,如下圖所示:
滑鼠選中內容,快速回饋問題
滑鼠選中存在疑惑的內容,即可快速回饋問題,我們將會跟進處理。
不再提示
10s後關閉
反馈已提交
网络繁忙