Webhooks erklärt: Signierte Payloads und Retries
Sie haben eine API entwickelt und müssen nun andere Dienste benachrichtigen, wenn Ereignisse eintreten. Sie richten einen Webhook-Endpunkt ein, stellen aber schnell fest, dass die zuverlässige Zustellung von HTTP-Anfragen schwieriger ist als es aussieht. Netzwerkfehler, böswillige Akteure und doppelte Ereignisse können Chaos verursachen. Dieser Leitfaden erklärt, wie Sie Webhooks mit signierten Payloads und Retries implementieren, um eine robuste Integration aufzubauen.
Was sind Webhooks?
Webhooks sind benutzerdefinierte HTTP-Callbacks. Wenn ein Ereignis in Ihrer Anwendung auftritt, senden Sie eine HTTP-POST-Anfrage an eine vom Abonnenten bereitgestellte URL. Dies ermöglicht Echtzeitkommunikation zwischen Diensten ohne Polling.
Beispielsweise könnte ein Zahlungsabwickler einen Webhook an Ihre App senden, wenn eine Abbuchung erfolgreich ist. Ihre App kann dann den Bestellstatus sofort aktualisieren.
Warum sollten Webhook-Payloads signiert werden?
Webhook-Endpunkte sind öffentlich zugänglich, sodass jeder gefälschte Anfragen senden kann. Ohne Verifizierung könnte Ihre App betrügerische Ereignisse verarbeiten. Das Signieren von Payloads stellt sicher, dass die Anfrage von Ihrem Dienst stammt und nicht manipuliert wurde.
Beim Signieren wird normalerweise ein Geheimnis verwendet, das zwischen Sender und Empfänger geteilt wird. Der Sender berechnet einen hashbasierten Nachrichtenauthentifizierungscode (HMAC) über den Payload und fügt ihn in einen Header ein. Der Empfänger berechnet den HMAC neu und vergleicht ihn.
So generieren und verifizieren Sie Signaturen
Die meisten Implementierungen verwenden HMAC-SHA256. Hier ist ein einfaches Beispiel in Python:
import hmac
import hashlib
import json
def generate_signature(payload, secret):
body = json.dumps(payload, separators=(',', ':')).encode('utf-8')
signature = hmac.new(secret.encode('utf-8'), body, hashlib.sha256).hexdigest()
return signature
def verify_signature(payload, signature, secret):
expected = generate_signature(payload, secret)
return hmac.compare_digest(expected, signature)
Fügen Sie beim Senden des Webhooks die Signatur in einen Header wie X-Signature ein. Der Empfänger extrahiert den Rohbody, berechnet den HMAC neu und vergleicht. Verwenden Sie immer eine Vergleichsfunktion mit konstanter Zeit, um Timing-Angriffe zu verhindern.
Implementierung von Retries für zuverlässige Zustellung
Webhooks werden über das Internet gesendet, daher sind Fehler unvermeidlich. Ihr Server könnte ausgefallen sein, das Netzwerk langsam sein oder der Abonnent einen Fehler zurückgeben. Retries mit exponentiellem Backoff sind unerlässlich.
Retry-Strategie
Ein üblicher Ansatz ist, mit zunehmenden Verzögerungen erneut zu versuchen: 1 Minute, 5 Minuten, 30 Minuten, 2 Stunden usw. Hören Sie nach einer maximalen Anzahl von Versuchen (z. B. 10) oder einem gesamten Zeitfenster (z. B. 24 Stunden) auf.
Wiederholen Sie nur bei bestimmten Bedingungen: Netzwerkfehler, 5xx-Antworten oder 429 (Too Many Requests). Wiederholen Sie nicht bei 4xx-Fehlern (außer 429), da diese auf einen Client-Fehler hinweisen, der durch Wiederholen nicht behoben wird.
Beispiel für Retry-Logik
Hier ist ein vereinfachter Retry-Mechanismus in Python unter Verwendung der requests-Bibliothek:
import requests
import time
from requests.exceptions import RequestException
def send_webhook(url, payload, secret, max_retries=5):
headers = {'Content-Type': 'application/json'}
signature = generate_signature(payload, secret)
headers['X-Signature'] = signature
for attempt in range(max_retries):
try:
response = requests.post(url, json=payload, headers=headers, timeout=10)
if response.status_code < 500 and response.status_code != 429:
return response.status_code
except RequestException:
pass
# Exponentielles Backoff mit Jitter
delay = (2 ** attempt) + (random.random() * 0.1)
time.sleep(delay)
return None # Nach Wiederholungen fehlgeschlagen
In der Produktion würden Sie fehlgeschlagene Versuche in eine Warteschlange stellen und asynchron verarbeiten. Tools wie Celery oder Cloud-Warteschlangen (AWS SQS, Google Cloud Tasks) können helfen.
Best Practices für Webhook-Sicherheit
- HTTPS verwenden: Senden Sie Webhooks immer über TLS, um Abhören zu verhindern.
- Zeitstempel einfügen: Fügen Sie dem Payload einen Zeitstempel hinzu und lehnen Sie Anfragen ab, die älter als ein paar Minuten sind, um Replay-Angriffe zu verhindern.
- Geheimnisse rotieren: Ändern Sie das Signaturgeheimnis regelmäßig und unterstützen Sie mehrere aktive Geheimnisse während der Rotation.
- URL validieren: Stellen Sie bei der Registrierung eines Webhooks sicher, dass die URL erreichbar ist und auf eine Testanfrage mit 2xx antwortet.
- Rate Limiting: Schützen Sie Ihren Webhook-Sender vor Missbrauch, indem Sie die Anzahl der Anfragen pro Abonnent begrenzen.
Umgang mit Duplikaten und Idempotenz
Retries können zu doppelten Zustellungen führen. Fügen Sie eine eindeutige Ereignis-ID in den Payload ein und lassen Sie den Empfänger verarbeitete IDs verfolgen. Wenn eine Ereignis-ID bereits gesehen wurde, ignorieren Sie sie.
Alternativ können Sie Ihre Ereignishandler idempotent gestalten. Beispielsweise sollte das Aktualisieren eines Datensatzes mit denselben Daten mehrmals denselben Effekt haben wie einmal.
Testen von Webhooks
Verwenden Sie Tools wie ngrok, um Ihren lokalen Server verfügbar zu machen und die Webhook-Zustellung zu testen. Simulieren Sie Fehler durch Rückgabe von Fehlercodes und überprüfen Sie, ob Retries wie erwartet erfolgen.
FAQ
Was ist ein signierter Webhook-Payload?
Ein signierter Payload enthält eine kryptografische Signatur (normalerweise HMAC), die es dem Empfänger ermöglicht zu überprüfen, ob die Anfrage von einer vertrauenswürdigen Quelle stammt und nicht verändert wurde.
Wie oft sollte ich einen fehlgeschlagenen Webhook wiederholen?
Das hängt von Ihren Zuverlässigkeitsanforderungen ab. Eine gängige Praxis sind 5-10 Wiederholungen mit exponentiellem Backoff über 24 Stunden. Ermöglichen Sie Abonnenten immer, eine Wiederholung manuell auszulösen.
Kann ich Webhooks ohne Signierung verwenden?
Ja, aber es ist riskant. Ohne Signierung kann jeder gefälschte Ereignisse senden. Signieren Sie Webhooks in der Produktion immer, um Betrug zu verhindern.
Bereit, Ihre Webhook-Payloads zu testen? Verwenden Sie unseren JSON Formatter, um JSON-Payloads vor dem Senden zu validieren und hübsch zu formatieren.