两种POST请求方式为何导致hash_hmac sha256计算结果不一致?
原因分析
差异的核心在于换行符的标准化处理以及表单与AJAX提交的内容差异:
- 换行符的DOM读取转换
在stringify函数中,你给bodyv赋值时使用了\r\n(Windows风格换行符)作为分隔符。但通过$("#bodyv").val()读取输入框值时,浏览器会自动将输入框中的\r\n标准化为\n(Unix风格换行符)。
- 表单提交时,浏览器会将输入框中的原始
\r\n做URL编码(转为%0D%0A)后发送,PHP接收后自动解码还原为\r\n,因此计算出的签名正确。 - AJAX请求发送的是被DOM标准化后的
\n版本内容,PHP处理的是仅含\n的字符串,和表单提交的原始内容不一致,导致哈希结果不同。
- 双重请求触发的干扰
#btn2既是表单提交按钮,又绑定了jQuery的click事件。点击按钮时两个逻辑同时执行:
- 先执行
stringify()更新bodyv,再发送AJAX请求; - 同时表单触发默认提交,发送的是包含原始
\r\n的bodyv值,这也是方法1结果正确的原因。
解决办法
要让AJAX请求和表单提交生成相同的签名,可按以下方式修改:
- 阻止表单默认提交行为
在jQuery的click事件中添加event.preventDefault(),避免重复请求:
$("#btn2").click(function(event){ event.preventDefault(); // 阻止表单默认提交 stringify(); // 后续AJAX逻辑 })
- 确保换行符一致
- 方式一:直接构造原始字符串发送,不通过DOM读取:
$("#btn2").click(function(event){ event.preventDefault(); let time = document.getElementsByName('time')[0].value; let body = JSON.stringify({ "data": { "serviceType": "MOTORCYCLE", "specialRequests": ["CASH_ON_DELIVERY"], "language": "en_PH", "stops": [ {"coordinates": {"lat": "0", "lng": "0"}, "address": "Innocentre, 72 Tat Chee Ave, Kowloon Tong"}, {"coordinates": {"lat": "0", "lng": "0"}, "address": "Canton Rd, Tsim Sha Tsui"} ], "isRouteOptimized": false, "item":{ "quantity":"12", "weight":"LESS_THAN_3_KG", "categories":["FOOD_DELIVERY","OFFICE_ITEM"], "handlingInstructions":["KEEP_UPRIGHT"] } } }); let rawBody = `${time.toString()}\r\nPOST\r\n/v3/quotations\r\n\r\n${body}`; $.post("postmanTest.php", {bodyv: rawBody}, function(data,status){ alert(data); } ) })
- 方式二:读取DOM值后将
\n替换回\r\n:
$("#btn2").click(function(event){ event.preventDefault(); stringify(); let $bodyv = $("#bodyv").val().replace(/\n/g, '\r\n'); $.post("postmanTest.php", {bodyv: $bodyv}, function(data,status){ alert(data); } ) })
内容的提问来源于stack exchange,提问作者Floben Dale Moro
相关产品推荐
相关产品推荐

