我正在尝试重新创建在 Postman 中获取的一部分 JavaScript 代码,并且需要在 Python 中执行相同的操作。 基本上我需要在 Python 中生成一个 HMAC SHA256,在与 API 通信时需要在所有请求上使用它。
使用我的凭据(app_id 和 app_secret)在 Postman(JavaScript 代码)中进行测试,一切运行良好。 在 Python 中,我收到 401 错误响应(错误的签名)。
JavaScript原代码:
let uuid = require('uuid');
const client_id = pm.environment.get("app_id").toString();
const client_secret = pm.environment.get("app_secret").toString();
let request_content_base64 = "";
let request_method = request.method;
let request_nonce = uuid.v4().toString();
let request_timestamp = Math.round(new Date().getTime() / 1000);
let body_string = pm.variables.replaceIn(pm.request.body.toString());
let request_url = pm.variables.replaceIn(pm.request.url.toString());
if (body_string) {
var md5 = CryptoJS.MD5(body_string);
request_content_base64 = CryptoJS.enc.Base64.stringify(md5);
}
let signature = `${client_id}${request_method}${request_url}${request_timestamp}${request_nonce}${request_content_base64}`;
let client_secret_string = CryptoJS.enc.Base64.parse(client_secret);
let signature_bytes = CryptoJS.HmacSHA256(signature, client_secret_string);
let signature_hashBase64 = CryptoJS.enc.Base64.stringify(signature_bytes);
pm.variables.set("hmac", `${client_id}:${signature_hashBase64}:${request_nonce}:${request_timestamp}`);
我的硬编码 Python 代码:
def generate_mac(uri, method, body=None):
app_id = 'my_secret_app_id'
app_secret = 'my_secret_app_secret_key'
app_secret = base64.b64decode(app_secret)
timestamp = int(time.time())
nonce = str(uuid.uuid4())
content = ""
if body is not None:
body_md5 = hashlib.md5(body.encode('utf-8')).digest()
content = base64.b64encode(body_md5).decode('utf-8')
message = app_id + method + uri + str(timestamp) + nonce + content
message_bytes = message.encode('utf-8')
signature = hmac.new(app_secret, msg=message_bytes, digestmod=hashlib.sha256).digest()
hashed = base64.b64encode(signature).decode('utf-8')
return "{}:{}:{}:{}".format(app_id, hashed, nonce, timestamp)
我正在使用 GET 请求作为:
data = {
'sample_key': 1,
'sample_key1': 10,
}
uri = 'https://api-serviceprovider-url/posts'
method = 'GET'
body = str(data)
hashed = generate_mac(uri, method, body)
head = {'Authorization': f"ApiKey {hashed}"}
r = requests.get(uri, headers=head)
生成签名,文档参考(翻译成英文):
首先,客户端需要创建一个字符串(MAC),它将包含要发送到 API 的请求中的所有数据:
AppId + HTTP Method + Nonce (unique string for each request) + URI + UNIX Timestamp + base64 string of md5 from payload
创建字符串后,必须使用最初提供的 appsecret 生成字符串的 SHA256 哈希。签名将由 AppId、签名、时间戳和随机数组成,由 .
分隔[ApiKey AppId:hash:nonce:timestamp]
尝试根据 python 代码块生成 HMAC 的 Python 版本,但没有成功。