Webhooks erklärt: Signierte Payloads und Retries
Warum Webhooks Signaturen und Retries benötigen
Sie haben einen Endpunkt erstellt, um Webhooks von einem Zahlungsanbieter oder einer SaaS-Plattform zu empfangen. Im Test funktioniert alles, aber in der Produktion stehen Sie vor zwei Problemen: Woher wissen Sie, dass die Anfrage wirklich vom Anbieter stammt, und was passiert, wenn Ihr Server ausgefallen oder langsam ist? Ohne signierte Payloads kann jeder eine Anfrage fälschen. Ohne Retries kann ein einzelner Netzwerkausfall ein Ereignis für immer verlieren.
Dieser Leitfaden erklärt, wie Sie beides korrekt implementieren. Wir behandeln HMAC-Signierung, Verifikationsschritte, Retry-Strategien und Idempotenz – die drei Säulen einer zuverlässigen Webhook-Verarbeitung.
Wie Webhook-Signaturen funktionieren
Eine Webhook-Signatur ist ein kryptografischer Hash, der beweist, dass der Payload von jemandem erstellt wurde, der ein gemeinsames Geheimnis kennt. Die meisten Anbieter verwenden HMAC-SHA256. Der Sender berechnet die Signatur über den rohen Request-Body (manchmal mit einem Zeitstempel) und fügt sie in einen Header ein. Der Empfänger berechnet sie neu und vergleicht.
Hier ist ein typischer Ablauf:
- Anbieter und Konsument teilen einen geheimen Schlüssel (konfiguriert im Dashboard des Anbieters).
- Der Anbieter erstellt den Payload, berechnet
HMAC-SHA256(secret, payload)und sendet ihn in einem Header wieX-Signature. - Der Konsument empfängt die Anfrage, liest den rohen Body, berechnet den HMAC neu und vergleicht mit einer zeitkonstanten Funktion.
- Wenn sie übereinstimmen, wird das Ereignis verarbeitet; andernfalls wird mit 401 abgelehnt.
Wichtig: Verwenden Sie immer den rohen Request-Body wie empfangen, nicht eine geparste und neu serialisierte Version. Die JSON-Serialisierung kann Leerzeichen und Schlüsselreihenfolge ändern und die Signatur brechen.
Zeitstempel hinzufügen, um Replay-Angriffe zu verhindern
Ein signierter Payload allein kann von einem Angreifer, der eine gültige Anfrage abfängt, wiedergegeben werden. Um dies zu mildern, fügen Sie einen Zeitstempel in die signierten Daten ein und lehnen Anfragen ab, die älter als ein paar Minuten sind. Zum Beispiel:
signed_payload = timestamp + "." + raw_body
signature = HMAC-SHA256(secret, signed_payload)
Der Konsument prüft, ob der Zeitstempel innerhalb eines akzeptablen Fensters liegt (z. B. 5 Minuten) und ob die Signatur übereinstimmt.
Implementierung der Signaturverifikation
Schauen wir uns ein konkretes Beispiel in Python mit Flask an. Wir verifizieren eine Signatur, die im Header X-Signature gesendet wird.
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(401)
raw_body = request.get_data()
expected = hmac.new(SECRET, raw_body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, signature):
abort(401)
# Ereignis verarbeiten
event = request.json
# ... Ereignis behandeln ...
return '', 200
Wichtige Punkte:
- Verwenden Sie
hmac.compare_digest(oder gleichwertig) für zeitkonstanten Vergleich, um Timing-Angriffe zu vermeiden. - Greifen Sie auf den rohen Body über
request.get_data()vor jeglicher Verarbeitung zu. - Geben Sie schnell 200 zurück; führen Sie schwere Verarbeitung asynchron durch.
Entwurf einer Retry-Strategie
Auch mit Signaturen können Webhooks fehlschlagen: Ihr Server könnte ausgefallen sein, einen 500 zurückgeben oder eine Zeitüberschreitung haben. Anbieter wiederholen in der Regel mit exponentiellem Backoff. Als Konsument sollten Sie auch Retries ordnungsgemäß behandeln.
Folgendes sollten Sie beachten:
- Idempotenz: Jedes Ereignis sollte eine eindeutige ID haben. Speichern Sie verarbeitete IDs, um doppelte Verarbeitung bei Wiederholungen zu vermeiden.
- Schnell antworten: Bestätigen Sie den Empfang mit einem 2xx-Status innerhalb weniger Sekunden. Stellen Sie das Ereignis für die Hintergrundverarbeitung in eine Warteschlange.
- Retry-Logik auf Ihrer Seite: Wenn Sie nachgelagerte Dienste aufrufen, implementieren Sie Retries mit Backoff und Circuit Breakern.
Die meisten Anbieter wiederholen bei Nicht-2xx-Antworten oder Zeitüberschreitungen, oft bis zu 24 Stunden mit zunehmenden Intervallen. Überprüfen Sie die Dokumentation Ihres Anbieters für Details.
Beispiel: Idempotenter Ereignishandler
Verwenden Sie eine Datenbanktabelle, um verarbeitete Ereignis-IDs zu verfolgen. Hier ist ein vereinfachtes Muster:
def handle_event(event_id, payload):
if db.exists('processed_events', event_id):
return # bereits behandelt
# Payload verarbeiten
db.insert('processed_events', event_id)
# ... eigentliche Arbeit ...
Für hohen Durchsatz verwenden Sie eine eindeutige Einschränkung für die Ereignis-ID und fangen Sie Fehler bei doppelten Schlüsseln ab.
Vergleich: Signierte vs. unsignierte Webhooks
| Aspekt | Signierte Payloads | Unsignierte Payloads |
|---|---|---|
| Sicherheit | Verifiziert die Authentizität des Senders | Jeder kann Anfragen fälschen |
| Replay-Schutz | Möglich mit Zeitstempeln | Keiner |
| Implementierungsaufwand | Mittel (HMAC + Zeitstempelprüfung) | Gering |
| Empfohlen für | Alle Produktions-Webhooks | Nur interne Tests |
Häufige Fallstricke und Best Practices
- Nicht vor der Verifikation parsen: Verifizieren Sie immer zuerst die Signatur auf dem rohen Body.
- HTTPS verwenden: Signaturen schützen die Integrität, aber HTTPS schützt die Vertraulichkeit.
- Geheimnisse rotieren: Unterstützen Sie während der Rotation mehrere aktive Geheimnisse, um Ausfallzeiten zu vermeiden.
- Fehler protokollieren: Zeichnen Sie Signaturabweichungen und Wiederholungen zum Debuggen auf.
- Mit echten Payloads testen: Verwenden Sie Tools wie webhook.site oder die CLI Ihres Anbieters, um Ereignisse zu simulieren.
FAQ
Was ist ein signierter Webhook-Payload?
Ein signierter Payload enthält eine kryptografische Signatur (normalerweise HMAC), mit der der Empfänger überprüfen kann, dass die Anfrage von einer vertrauenswürdigen Quelle stammt und nicht manipuliert wurde.
Wie behandle ich Webhook-Wiederholungen, ohne Aktionen zu duplizieren?
Machen Sie Ihren Handler idempotent, indem Sie Ereignis-IDs verfolgen. Prüfen Sie vor der Verarbeitung, ob die ID bereits behandelt wurde; wenn ja, geben Sie Erfolg zurück, ohne die Arbeit zu wiederholen.
Kann ich Webhooks ohne Signaturen verwenden?
Für die Produktion wird davon abgeraten. Ohne Signaturen können Sie legitime Anfragen nicht von gefälschten unterscheiden. Verifizieren Sie immer Signaturen, wenn verfügbar.
Beim Debuggen von Webhook-Payloads oder Analysieren von Server-Logs kann der JSON Formatter Ihnen helfen, JSON-Strukturen schnell zu inspizieren und zu validieren.