HMAC签名在前端加密时,为什么服务端验证总是失败?
我在给登录接口加HMAC签名验证时遇到了问题。按照文档用CryptoJS生成签名,把时间戳和参数按字母排序后拼接,但服务端一直返回”签名无效”。试过确认密钥和算法都正确,连请求头的Content-Type都按服务端要求改成了application/json,还是不行:
const params = JSON.stringify({
timestamp: Date.now(),
username: 'test',
password: '123'
});
const hmac = CryptoJS.HmacSHA256(params, 'secret-key').toString();
服务端提示签名计算方式有问题,难道是参数排序规则或者时间戳格式哪里没对齐?或者加密前的字符串处理漏了什么步骤?
先确认服务端是怎么拼接参数的,跟着它做就完事了。
关键点在于:签名字符串的构造规则必须和服务端保持一致。比如:
时间戳是否要求为10位或13位?
参数是否要进行排序?排序方式是按key的ASCII还是其他?
是否需要拼接方式是
key1=value1&key2=value2还是key1value1key2value2或者其他?是否对参数值进行了encode处理?
从你贴的代码看,你是直接对整个params对象进行了stringify,然后拿这个字符串去签名。但服务端可能压根不是这么拼的。
我猜你服务端那边的签名逻辑大概是这样处理的:
把参数按key排序
拼接成key=value的形式,然后用&连接起来
最后加上密钥进行HMAC
所以你的前端代码应该重构为:
这样拼出来的字符串,才和服务端预期的签名原文一致。
建议你和服务端同学对齐签名字符串的拼接规则,包括是否对参数做encode,顺序、格式这些细节。