Webhook 詳解:簽章負載與可靠重試

Backend2026-10-20TryQuickToolBox

你剛剛整合了第三方支付閘道或 CI/CD 服務,現在需要即時通知。Webhook 就是答案——但沒有適當的安全性和可靠性,它們可能會成為挫折的來源。攻擊者可以偽造請求,網路故障可能導致事件遺失。在本指南中,我們將探討如何使用簽章負載保護 Webhook,並實作穩健的重試機制。

什麼是 Webhook?

Webhook 是由特定事件觸發的使用者定義 HTTP 回呼。當事件發生時(例如付款成功),來源服務會向您提供的 URL 發送 HTTP POST 請求,其中包含事件資料。這種推送模型比輪詢更有效率,並能實現即時反應。

然而,Webhook 引入了兩個挑戰:真實性(確保請求來自預期的發送者)和可靠性(確保不會遺漏事件)。

使用簽章負載保護 Webhook

簽章負載使用發送者和接收者之間共享的密鑰來建立加密簽章。發送者將此簽章包含在標頭中,接收者則驗證它以確認負載的完整性和來源。

HMAC 簽章如何運作

HMAC(基於雜湊的訊息驗證碼)是標準做法。發送者使用共享密鑰對請求主體計算 HMAC,並將其包含在如 X-Signature 的標頭中。接收者重新計算 HMAC 並進行比較。

// 範例:在 Node.js 中產生簽章
const crypto = require('crypto');

function generateSignature(payload, secret) {
  return crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');
}

// 在接收端,驗證:
function verifySignature(payload, secret, receivedSignature) {
  const expected = generateSignature(payload, secret);
  // 使用定時安全比較以防止時序攻擊
  return crypto.timingSafeEqual(
    Buffer.from(expected, 'hex'),
    Buffer.from(receivedSignature, 'hex')
  );
}

重點:

額外的安全措施

實作可靠的重試

網路是不可靠的。Webhook 可能因逾時、伺服器錯誤或暫時性中斷而失敗。穩健的重試策略可確保最終傳遞,而不會壓垮您的系統或發送者。

重試最佳實務

  1. 指數退避: 增加重試之間的延遲(例如 1 秒、2 秒、4 秒、8 秒...)。
  2. 最大重試次數限制: 限制嘗試次數(例如 5 次)以避免無限迴圈。
  3. 無效信件佇列: 耗盡重試後,儲存失敗事件以供手動檢查。
  4. 冪等性: 確保多次處理同一事件不會導致重複的副作用。

實務中的冪等性

在負載中包含唯一的事件 ID。在接收端,追蹤已處理的 ID(在資料庫或快取中)並忽略重複項。例如:

// 冪等處理的虛擬碼
if (eventStore.exists(event.id)) {
  return 200; // 已處理
}
// 處理事件...
eventStore.save(event.id);

優雅地處理失敗

快速回應 2xx 狀態以確認收到。如果處理需要時間,將事件加入佇列並非同步處理。僅對需要重試的暫時性錯誤返回 5xx;對於永久性錯誤(例如無效負載),返回 4xx 以防止無效的重試。

比較:推送 vs. 輪詢

面向 Webhook(推送) 輪詢
延遲 近乎即時 取決於間隔
效率 僅在事件發生時發送 持續請求
複雜度 需要重試/安全邏輯 較簡單但浪費資源

測試您的 Webhook 實作

使用 ngrok 等工具公開您的本機伺服器並模擬 Webhook 傳遞。透過故意使請求失敗來驗證簽章驗證和重試行為。

常見問題

什麼是簽章 Webhook 負載?

簽章負載包含加密簽章(通常是 HMAC),允許接收者使用共享密鑰驗證請求的真實性和完整性。

我應該重試失敗的 Webhook 多少次?

沒有通用的數字,但通常會使用指數退避進行 3–5 次重試。之後,記錄失敗以供手動審查。

我可以在沒有 HTTPS 的情況下使用 Webhook 嗎?

技術上可以,但非常不安全。始終使用 HTTPS 以防止竊聽和中間人攻擊。

準備好檢查 Webhook 負載了嗎?使用我們的 JSON 格式化工具 快速美化並驗證 JSON 負載。