Webhooks 解析:簽名載荷與重試機制

Backend2026-11-01TryQuickToolBox

你剛剛整合了一個會向你的端點發送 Webhook 的第三方服務。在測試環境中一切正常,但在生產環境中你卻注意到事件遺漏、重複傳遞以及偶爾的安全問題。Webhook 概念簡單但實作起來卻很棘手——尤其是在驗證真實性和處理失敗方面。

本指南說明如何使用簽名載荷保護 Webhook,並實作穩健的重試機制,以便你建立可靠的整合。

什麼是 Webhook?

Webhook 是使用者定義的 HTTP 回呼。當來源系統中發生事件(例如付款完成)時,它會向您指定的 URL 發送 HTTP POST 請求,其中包含有關事件的資料。這允許服務之間進行即時通訊,而無需輪詢。

但 Webhook 帶來了挑戰:您如何知道請求確實來自預期的發送者?如果您的端點暫時宕機怎麼辦?這就是簽名載荷和重試發揮作用的地方。

使用簽名載荷保護 Webhook

簽名載荷使用密碼學簽名來證明請求源自發送者且未被篡改。常見的方法是使用共享密鑰的 HMAC(基於雜湊的消息驗證碼)。

HMAC 簽名如何運作

發送者使用密鑰對請求主體(有時還包括時間戳等標頭)計算 HMAC。簽名在標頭中發送(例如 X-Signature)。您的伺服器重新計算 HMAC 並將其與收到的簽名進行比較。如果它們匹配,則請求是真實的。

以下是使用 Flask 的 Python 最小範例:

import hmac
import hashlib
from flask import Flask, request, abort

app = Flask(__name__)
SECRET = b'your_shared_secret'

@app.route('/webhook', methods=['POST'])
def webhook():
    signature = request.headers.get('X-Signature')
    if not signature:
        abort(400, 'Missing signature')
    body = request.get_data()
    expected = hmac.new(SECRET, body, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(expected, signature):
        abort(401, 'Invalid signature')
    # Process the event
    return '', 200

重點:

額外的安全措施

實作可靠的重試

Webhook 消費者可能會失敗:您的伺服器可能宕機,或者處理可能逾時。發送者應使用指數退避重試失敗的傳遞。作為消費者,您必須優雅地處理重試。

發送者端(如果您正在建立 Webhook 系統)

  1. 快速返回 2xx: 在處理之前確認收到以避免逾時。使用佇列進行非同步工作。
  2. 失敗時重試: 如果在逾時時間內(例如 5 秒)未收到 2xx,則以遞增的延遲重試(例如 1 秒、5 秒、30 秒、5 分鐘、30 分鐘)。
  3. 限制重試次數: 在最大嘗試次數(例如 5 次)後,將傳遞標記為失敗並發出警報。
  4. 包含唯一事件 ID: 以便消費者可以去重。

消費者端(您的端點)

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

方法 安全性 複雜度 重放保護
HMAC 簽名 高(完整性 + 真實性) 中等 是(帶時間戳)
基本驗證 低(標頭中的憑證) 低 否
IP 允許清單 中(網路層級) 低 否

在本機測試 Webhook

在開發過程中,您需要一個公開 URL 來接收 Webhook。ngrok 或 localtunnel 等工具可以公開您的本機伺服器。始終使用模擬失敗測試簽名驗證和重試行為。

檢查 Webhook 載荷時,您可能需要格式化 JSON 以提高可讀性。JSON Formatter 可以幫助您美化列印並驗證 JSON 主體。

常見問題

什麼是簽名 Webhook 載荷?

簽名載荷包含密碼學簽名(通常是 HMAC),允許接收者驗證請求的真實性和完整性。

Webhook 應該重試多少次?

沒有固定次數;常見做法是使用指數退避重試 3 到 10 次。關鍵是在可靠性和資源使用之間取得平衡,並對持續失敗發出警報。

我可以使用沒有簽名的 Webhook 嗎?

不建議。沒有簽名,您無法驗證發送者,使您的端點容易受到欺騙。在生產環境中始終使用簽名。

準備好除錯您的 Webhook 載荷了嗎?試試我們的 JSON Formatter 快速驗證和格式化 JSON 資料。