说明
ak/sk获取方式:GMP首页--》项目管理--》Openapi鉴权--》创建ak/sk
(详见鉴权码计算脚本)
import time import hashlib import hmac import json def _do_sign(ak, sk, expiration, text): print("text = ", text) sign_key_info = 'ak-v1/%s/%d/%d' % (ak, time.time(), expiration) print("sign_key_info = ", sign_key_info) sign_key = _sha256_hmac(sk, sign_key_info) print("sign_key = ", sign_key) sign_result = _sha256_hmac(sign_key, text) return '%s/%s' % (sign_key_info, sign_result) def _canonical_method(method): return "HTTPMethod:" + method def _canonical_url(url): return "CanonicalURI:" + url def _canonical_param(params): res = 'CanonicalQueryString:' if not params: return res kvs = [] for k, v in params.items(): kvs.append('{}={}'.format(k, v)) return res + '&'.join(kvs) def _canonical_body(body): res = "CanonicalBody:" if not body: return res return res + body def _sha256_hmac(key, data): return hmac.new(str.encode(key, 'utf-8'), str.encode(data, 'utf-8'), hashlib.sha256).hexdigest() """ :param ak:accessKey :param sk:secretKey :param expiration_seconds:过期时间,单位秒 :param method:方法,GET, POST, PUT :param uri_path:请求的path,非完整的url :param params:请求参数 :param body:请求的json体 :return: """ def sign(ak, sk, expiration_seconds, method, uri_path, params, body): canonical_method = _canonical_method(method) canonical_url = _canonical_url(uri_path) canonical_param = _canonical_param(params) canonical_body = _canonical_body(body) text = '{}\n{}\n{}\n{}'.format(canonical_method, canonical_url, canonical_param, canonical_body) return _do_sign(ak, sk, expiration_seconds, text) ak = "1-8256" sk = "JZBMEclYMcQRajsweQr4Pokh7zegTb4tAc5n0qmvTh1nEQx" expiration_seconds = 300 method = "POST" # 请求的path,非完整的url uri = "/gmp/openapi/v1/resource_space/getResourceSpaceDefaultMaterial" params = {} request_body = { "app_id": 1, "data_ver": 0 } auth = sign(ak, sk, expiration_seconds, method, uri, params, json.dumps(request_body)) print(auth)
const crypto = require('crypto'); function hash(ak, sk, expiration_seconds, method, path, params, body) { const timestamp = (+new Date() / 1000).toFixed(0); const signKeyInfo = `ak-v1/${ak}/${timestamp}/${expiration_seconds}`; const signKey = sha256HMAC(sk, signKeyInfo); const data = canonicalRequest(method, path, params, body); const signResult = sha256HMAC(signKey, data); return signKeyInfo + '/' + signResult; } function sha256HMAC(sk, data) { const hmac = crypto.createHmac('sha256', sk) return hmac.update(data).digest('hex') } function canonicalRequest(method, url, params, body) { let cm = canonicalMethod(method); let cu = canonicalUrl(url); let cp = canonicalParam(params); let cb = canonicalBody(body); return cm + '\n' + cu + '\n' + cp + '\n' + cb; } function canonicalMethod(method) { return 'HTTPMethod:' + method; } function canonicalUrl(url) { return 'CanonicalURI:' + url; } function canonicalParam(params) { let res = 'CanonicalQueryString:' if (!params) { return res; } return res + queryString(params); } function canonicalBody(body) { res = "CanonicalBody:" if (!body){ return res; } return res + body; }
AuthUtil.java
import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Map; public class AuthUtils { /** * * @param ak accessKey * @param sk secretKey * @param expirationSeconds 过期时间,单位秒 * @param method 方法,GET, POST, PUT * @param uriPath 请求的path,非完整的url * @param params 请求参数 * @param body 请求的json体 * @return */ public static String sign(String ak, String sk, int expirationSeconds, String method, String uriPath, Map<String, String> params, String body) { String cm = canonicalMethod(method); String cu = canonicalUrl(uriPath); String cp = canonicalParam(params); String cb = canonicalBody(body); String text = cm + "\n" + cu + "\n" + cp + "\n" + cb; return doSign(ak, sk, expirationSeconds, text); } private static String canonicalMethod(String method) { return "HTTPMethod:" + method; } private static String canonicalUrl(String url) { return "CanonicalURI:" + url; } private static String canonicalParam(Map<String, String> params) { String res = "CanonicalQueryString:"; if (params == null || params.isEmpty()) { return res; } for (String key : params.keySet()) { res += formatKeyValue(key, params.get(key)) + "&"; } return res.substring(0, res.length() - 1); } private static String formatKeyValue(String key, String value) { return key + "=" + value; } private static String canonicalBody(String body) { String res = "CanonicalBody:"; if (body == null) { return res; } else { return res + body; } } private static String doSign(String ak, String sk, int expiration, String text) { String signKeyInfo = "ak-v1/" + ak + "/" + (int) (System.currentTimeMillis() / 1000) + "/" + expiration; String signKey = sha256Hmac(signKeyInfo, sk); String signResult = sha256Hmac(text, signKey); return signKeyInfo + "/" + signResult; } private static String sha256Hmac(String message, String secret) { String hash = ""; try { Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256"); sha256_HMAC.init(secret_key); byte[] bytes = sha256_HMAC.doFinal(message.getBytes()); hash = byteArrayToHexString(bytes); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } return hash; } private static String byteArrayToHexString(byte[] b) { StringBuilder hs = new StringBuilder(); String stmp; for (int n = 0; b != null && n < b.length; n++) { stmp = Integer.toHexString(b[n] & 0XFF); if (stmp.length() == 1) { hs.append('0'); } hs.append(stmp); } return hs.toString().toLowerCase(); } }
调用
import java.util.LinkedHashMap; import java.util.Map; public class AuthGenDemo { //分配的accessKey和secretKey private static String accessKey = "****"; private static String secretKey = "****"; // 单位秒 private static Integer expirationSeconds = 300; public static void main(String[] args) { String method = "POST"; // 请求的path,非完整的url String uri = "/dataprofile/openapi/v1/751/users/185"; Map<String, String> exampleQueryParams = new LinkedHashMap<>(); exampleQueryParams.put("set_once", "true"); String exampleQueryBodyJson = "{\"name\":\"name\",\"value\":\"zhangsan\"}"; String authorization = AuthUtils.sign(accessKey, secretKey, expirationSeconds, method, uri, exampleQueryParams, exampleQueryBodyJson); System.out.println("authorization: " + authorization); } }
用于计算的Body请务必与最终发送的body完全一致
在鉴权脚本中替换内容并计算签名:
运行脚本
将CanonicalBody:后的内容替换到postman的请求体输入框中(注意前后不要有空格/换行):
在Header中添加字段Authorization并添加上图框2中的内容:
发送请求即可。
var CryptoJS = require('crypto-js'); console.log("bodyData = " + pm.request.url); // 获取当前请求的body数据 var u=pm.request.url.toString() var p = u.split('?')[1] var bodyData = pm.request.body.toString(); const paramArr = p.match(/([^&=]+)=?([^&]*)/g); const paramsData = new Map(); paramArr.map((param) => { const [key, val] = param.split("="); paramsData.set(key,val); }) console.log(paramsData); // 打印到控制台 // console.log("paramsData = " + paramsData); console.log("bodyData = " + bodyData); const ak = "5er18yxAa4f"; const sk = "4514514515"; const sign_method = pm.request.method; let paths = JSON.parse(JSON.stringify(pm.request.url.path)) if (pm.request.url.path[0].startsWith('fedev-')){ paths.splice(0, 1) } let path = '/' + paths.join('/') let sign = hash(ak,sk,3600,sign_method,path,paramsData,bodyData) pm.request.headers.add({key: 'Authorization', value: sign}) // const crypto = require('crypto'); function hash(ak, sk, expiration_seconds, method, path, params, body) { const timestamp = (+new Date() / 1000).toFixed(0); const signKeyInfo = `ak-v1/${ak}/${timestamp}/${expiration_seconds}`; const signKey = sha256HMAC(sk, signKeyInfo); const data = canonicalRequest(method, path, params, body); const signResult = sha256HMAC(signKey, data); return signKeyInfo + '/' + signResult; } function sha256HMAC(sk, data) { // const hmac = CryptoJS.SHA256(sk) return CryptoJS.HmacSHA256(data,sk).toString(CryptoJS.enc.Hex) } function canonicalRequest(method, url, params, body) { let cm = canonicalMethod(method); let cu = canonicalUrl(url); let cp = canonicalParam(params); let cb = canonicalBody(body); return cm + '\n' + cu + '\n' + cp + '\n' + cb; } function canonicalMethod(method) { return 'HTTPMethod:' + method; } function canonicalUrl(url) { return 'CanonicalURI:' + url; } function canonicalParam(params) { let res = 'CanonicalQueryString:' if (!params) { return res; } return res + queryString(params); } function queryString(params) { var arrayObj=Array.from(params); console.log(arrayObj) arrayObj.sort(function(a,b){return a[0].localeCompare(b[0])}); var res ='' for (var [key, value] of arrayObj) { res=res+key + '=' + value+'&'; console.log("res"+res) } if (res!=''){ res= res.substr(0,res.length-1) } console.log("res"+res) return res; } function canonicalBody(body) { let res = "CanonicalBody:" if (!body){ return res; } return res + body; }