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

Facebook Webhook签名验证失败问题求助

Facebook Webhook签名验证不匹配问题

我正在开发一款接收Facebook Webhooks payload的应用,每次调用时Facebook会提供签名,我需要验证签名来确保payload的完整性和来源。我严格按照官方文档的步骤和代码实现,用App Secret计算SHA-256签名,但生成的签名始终和Facebook在x-hub-signature-256头里发送的不匹配。

我用Lead Ads测试工具或者Webhook注册页的测试按钮发送请求,自己代码生成的签名和在线HMAC SHA256工具计算的结果一致,但就是和Facebook发来的对不上。我还试过Stack Overflow上的C#代码,生成的签名也和JS代码、在线工具一致,但还是和Facebook的签名不匹配。

我的JavaScript代码

const express = require("express"),
bodyParser = require("body-parser"),
{ urlencoded, json } = require("body-parser"),
app = express();
const crypto = require("crypto");

app.use(bodyParser.json({
    verify: (req, res, buf) => {
        req.rawBody = buf
    }
}));

function verifyRequestSignature(req, res, buf) {
  var signature = req.headers["x-hub-signature-256"];
  if (!signature) {
    console.warn(`Couldn't find "x-hub-signature-256" in headers.`);
  } else {
    var elements = signature.split("=");
    var signatureHash = elements[1];
    var expectedHash = crypto
      .createHmac("sha256", "AppSecret")
      .update(buf)
      .digest("hex");
    console.log(expectedHash);
    
    if (signatureHash != expectedHash) {
      throw new Error("Couldn't validate the request signature.");
    }
  }
}

// Handle incoming requests
app.post("/webhook", (req, res) => {
  try {
    verifyRequestSignature(req, res, req.rawBody);
    // Handle the incoming webhook event here...
    res.status(200).send("EVENT_RECEIVED");
  } catch (err) {
    console.error(err);
    res.sendStatus(403);
  }
});

// Start the server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server listening on port ${PORT}`);
});

示例数据

App-secret: 3f1e071f97065865829855e7b6e69dc8
Payload: {"entry":[{"id":"0","time":1683656757,"changes":[{"field":"leadgen","value":{"ad_id":"444444444","form_id":"444444444444","leadgen_id":"444444444444","created_time":1683656757,"page_id":"444444444444","adgroup_id":"44444444444"}}]}],"object":"page"}
Expected/Calculated signature: f5092edd80ab944fb1c66cf5d2f5534b100e16d18b117187635b55b2f4e6fc91
Signature Received: sha256=6f11c3490dbdf8e63af0287f40ccf159a12cac8e3f3213f09cc1d1247ceaa386

有没有人能帮我找出签名不匹配的原因?


排查方向及解决方案

  • 确认App Secret准确性:检查代码中的AppSecret是否是应用的真实密钥,不要混淆应用ID、页面AccessToken等其他凭证,确保没有额外的空格或换行符。
  • 校验原始请求体一致性:Facebook基于原始字节流计算签名,你需要确认rawBody是未被修改的请求原始数据。可以打印buf.toString()和测试工具发送的Payload逐字符对比,排查是否有中间件(代理、负载均衡)修改了请求体的空格、编码或转义字符。
  • 检查字符编码:确保计算HMAC时使用的是Payload的UTF-8编码字节流,Node.js的crypto.update默认处理Buffer,避免将buf转成其他编码的字符串后再传入计算。
  • 测试真实请求:Lead Ads测试工具的请求可能和真实生产请求有细微差异,尝试触发一次真实的Lead Ads Webhook请求,再验证签名是否匹配。
  • 排查中间件干扰:确认没有其他Express中间件(如压缩、解码类中间件)在body-parser前后修改了请求体,这会直接导致原始字节流变化,哈希计算错误。

内容的提问来源于stack exchange,提问作者Vatsal Arya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 22:44:58