Webhooks 詳解:簽名負載與重試邏輯

Backend2026-10-28TryQuickToolBox

你已經建立了一個 API,現在需要在事件發生時通知其他服務。輪詢效率低下,所以你轉向 Webhooks。但很快你會發現 Webhooks 可能失敗、被偽造或導致重複處理。本文說明如何使用簽名負載保護 Webhooks,並實作穩健的重試邏輯。

什麼是 Webhooks?

Webhooks 是使用者定義的 HTTP 回呼。當你的系統中發生事件(例如付款成功),你會向訂閱者提供的 URL 發送 HTTP POST 請求。負載通常包含 JSON 或表單格式的事件資料。

Webhooks 讓服務之間能夠即時通訊,無需不斷輪詢。它們被支付閘道、CI/CD 工具和 SaaS 平台廣泛使用。

為什麼要保護 Webhooks?

沒有安全防護,任何知道 Webhook URL 的人都可以發送偽造請求,導致資料損壞或詐騙。此外,攻擊者可能重放舊請求。使用共享密鑰對負載簽名可確保真實性和完整性。

使用 HMAC 簽署負載

HMAC(基於雜湊的訊息驗證碼)是簽署 Webhooks 的常見方法。發送方和接收方共享一個密鑰。發送方使用密鑰計算負載的 HMAC,並將其包含在標頭中(例如 X-Signature)。接收方重新計算 HMAC 並進行比較。

逐步說明:發送簽名 Webhook

  1. 建立負載(JSON)。
  2. 使用密鑰計算負載的 HMAC-SHA256。
  3. 將十六進位摘要包含在標頭中,例如 X-Signature: sha256=...。
  4. 發送 POST 請求。
// Node.js 範例,使用 crypto
const crypto = require('crypto');
const secret = 'your_shared_secret';
const payload = JSON.stringify({ event: 'payment.success', amount: 100 });
const signature = crypto.createHmac('sha256', secret).update(payload).digest('hex');
// 發送 POST 請求,標頭包含 X-Signature: sha256=signature

驗證簽名

在接收方,提取簽名標頭,計算原始請求主體的 HMAC,並使用恒定時間比較來防止時序攻擊。

// Express.js 範例
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-signature'];
  const computed = crypto.createHmac('sha256', secret).update(req.rawBody).digest('hex');
  if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(computed))) {
    return res.status(401).send('Invalid signature');
  }
  // 處理負載
  res.status(200).send('OK');
});

注意:確保使用原始主體,而不是解析後的 JSON,因為解析可能會改變負載。

防止重放攻擊

在簽名負載中包含時間戳,並拒絕超過幾分鐘的請求。同時,包含唯一的事件 ID 並儲存已處理的 ID 以避免重複。

可靠交付的重試邏輯

Webhook 端點可能離線或緩慢。實作具有指數退避和抖動的重試。設定最大重試次數(例如 5 次)和每個請求的超時時間。

重試策略

範例重試排程:第 1 次重試在 5 秒後,第 2 次在 30 秒後,第 3 次在 2 分鐘後,第 4 次在 10 分鐘後,第 5 次在 1 小時後。

處理失敗

如果所有重試都失敗,記錄失敗並通知訂閱者(例如透過電子郵件或儀表板)。提供手動重新發送 Webhooks 的方式。

比較:簽名負載 vs. 基本驗證

方法 安全性 複雜度 重放保護
HMAC 簽名負載 高 中等 是(含時間戳)
基本驗證 低 低 否
標頭中的 API 金鑰 中 低 否

最佳實踐

常見問題

如何驗證 Webhook 簽名?

使用你的密鑰計算原始請求主體的 HMAC,並使用恒定時間比較將其與簽名標頭進行比較。

如果 Webhook 失敗該怎麼辦?

實作具有指數退避和抖動的重試。如果所有重試都失敗,記錄失敗並提供手動重新發送選項。

我可以使用未簽名的 Webhooks 嗎?

不建議。沒有簽名,你無法驗證發送方,使你的系統容易受到偽造和重放攻擊。

測試 Webhook 負載時,你可能需要檢查 JSON 回應。使用我們的 JSON Formatter 快速美化並驗證 JSON 資料。