PHP Laravel验证SHA256withRSA类型Webhook签名持续失败如何处理
问题根因
- 算法选型错误:你使用的
hash_hmac是用于HMAC对称签名校验的函数,而第三方采用的是SHA256withRSA非对称签名,两类签名逻辑完全不互通,这是校验失败的核心原因。 - 签名格式处理错误:官方C#示例中会先将传入的签名做Base64解码后再执行校验,你直接取Header中的Base64编码字符串与计算结果对比,格式不匹配。
- 未使用RSA公钥验签逻辑:非对称签名校验需要使用对方提供的RSA公钥对签名做解密校验,你当前的逻辑完全没有用到RSA公钥的验签能力。
修正后代码(Laravel 适用)
public function isValid(Request $request) : bool { $signature = $request->header('X-Signature'); if (empty($signature)) { return false; } // 处理Header中签名可能带的前后引号 $signature = trim($signature, '"'); // 对签名做Base64解码,和官方C#示例逻辑对齐 $decodedSignature = base64_decode($signature, true); if (!$decodedSignature) { return false; } // 替换为你拿到的完整公钥,注意首尾需要保留-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----标记 $publicKey = "-----BEGIN PUBLIC KEY-----\r\nMIIBIjAN......\r\n-----END PUBLIC KEY-----"; $publicKeyRes = openssl_pkey_get_public($publicKey); if (!$publicKeyRes) { return false; } // 直接使用原始请求体校验,不要用$request->all()转JSON的结果,避免序列化差异导致校验失败 $payload = $request->getContent(); // 执行SHA256withRSA验签 $verifyResult = openssl_verify($payload, $decodedSignature, $publicKeyRes, OPENSSL_ALGO_SHA256); openssl_free_key($publicKeyRes); // openssl_verify返回1代表验签通过,0代表不匹配,false代表执行出错 return $verifyResult === 1; }
额外注意事项
- 确保你拿到的公钥格式完整,首尾的
-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----标记不要遗漏,每一行的长度符合PEM格式要求。 - 不要自行将
$request->all()序列化后作为校验payload,JSON序列化时的空格、换行、键值顺序差异都会导致校验失败,必须使用$request->getContent()拿到的原始请求体。
内容的提问来源于stack exchange,提问作者oliverbj
相关产品推荐
相关产品推荐

