You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript与Python生成的HMAC不匹配,疑因引号问题求助

HMAC生成不一致问题排查

JavaScript客户端实现

客户端通过以下代码生成HMAC:

generateHMAC: function (payload) {
  return new Promise((resolve) => {
    let hmacpsk = app.get('secret_key');
    const hmac = crypto.createHmac('sha256', hmacpsk).update(JSON.stringify(payload)).digest('hex');
    resolve(hmac);
  })
}

对应的payload:

{"patients":[{"id":96,"position":[40.475268,-3.6957545],"area_id":38,"visit":30}],"doctors":[{"id":18,"position":[40.45993,-3.686387],"area_id":38,"start_timestamp":"2022-12-11T23:00:00.000Z","visit":240}],"areas":[{"area_id":38,"transport":"walking"}]}

JSON.stringify(payload)的输出(标准JSON格式,双引号、无额外空格):

"{\"patients\":[{\"id\":96,\"position\":[40.475268,-3.6957545],\"area_id\":38,\"visit\":30}],\"doctors\":[{\"id\":18,\"position\":[40.45993,-3.686387],\"area_id\":38,\"start_timestamp\":\"2022-12-11T23:00:00.000Z\",\"visit\":240}],\"areas\":[{\"area_id\":38,\"transport\":\"walking\"}]}"

生成的哈希值:

84257087ef9cf31f376a8b39e36ac0d97de91d53c8e373cb1e936a51ca5664a2

Python服务端实现

服务端当前代码:

#get the body of the request
values = json.loads(request.get_data(as_text=True))
#generate new hmac
clave=hmac.new(b"secret_key", bytes(str(values), 'utf-8'), digestmod=hashlib.sha256).hexdigest()
print("The new key is:")
print (clave)

str(values)的输出(Python字典字符串表示,单引号):

"{'patients':[{'id':96,'position':[40.475268,-3.6957545],'area_id':38,'visit':30}],'doctors':[{'id':18,'position':[40.45993,-3.686387],'area_id':38,'start_timestamp':'2022-12-11T23:00:00.000Z','visit':240}],'areas':[{'area_id':38,'transport':'walking'}]}"

生成的哈希值:

a156bdf7a0c05443337bbf02ebe555b9004d275089c6bc5dae2ebff64d01f170

问题

两端生成的HMAC不一致,怀疑是引号问题但替换后仍未解决,请问问题出在哪里?


问题根源与解决方案

核心问题

Python端使用str(values)序列化对象是错误的:这是Python字典的自定义字符串表示,并非标准JSON格式,和JS的JSON.stringify输出存在多处关键差异:

  • 引号类型:Python用单引号,JSON标准要求双引号
  • 格式细节:str(values)可能包含额外空格、不同的键顺序(旧Python版本),甚至特殊字符的处理差异

这些差异会导致HMAC计算的原始字符串完全不同,最终哈希值自然不一致。

解决方案

方案1:直接使用原始请求体字符串(最优)

JS端是对JSON.stringify(payload)的结果生成HMAC,而这个结果就是请求的原始Body内容。因此Python端无需解析JSON,直接用原始请求体字符串计算HMAC:

import hmac
import hashlib

# 获取原始请求体文本
raw_body = request.get_data(as_text=True)
# 直接用原始字符串生成HMAC
clave = hmac.new(b"secret_key", raw_body.encode('utf-8'), digestmod=hashlib.sha256).hexdigest()
print("The new key is:", clave)

方案2:解析后重新序列化(需严格对齐格式)

如果必须先解析JSON做处理,再生成HMAC,要使用json.dumps()而非str(),并指定参数和JSON.stringify对齐:

import json
import hmac
import hashlib

values = json.loads(request.get_data(as_text=True))
# 生成和JSON.stringify一致的标准JSON字符串
json_str = json.dumps(
    values,
    separators=(',', ':'),  # 去掉默认空格,和JS紧凑格式一致
    ensure_ascii=False,     # 非ASCII字符处理和JS对齐
    sort_keys=False         # 保持键的顺序(Python3.7+默认保留插入顺序)
)
clave = hmac.new(b"secret_key", json_str.encode('utf-8'), digestmod=hashlib.sha256).hexdigest()
print("The new key is:", clave)

内容的提问来源于stack exchange,提问作者Paloma Jimeno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 19:05:22