Webhooks erklärt: Signierte Payloads und Retry-Strategien
Sie haben gerade ein Zahlungsgateway oder einen CI/CD-Dienst integriert und müssen nun Echtzeit-Ereignisse empfangen. Sie haben einen Endpunkt eingerichtet, stehen aber bald vor zwei kritischen Fragen: Wie stellen Sie sicher, dass die Anfrage tatsächlich vom Dienst stammt? Und was passiert, wenn Ihr Server nicht erreichbar ist, wenn ein Ereignis ausgelöst wird? Dieser Artikel beantwortet beide Fragen, indem er signierte Payloads und Retry-Strategien erklärt – das Rückgrat zuverlässiger Webhooks.
Was sind Webhooks?
Webhooks sind benutzerdefinierte HTTP-Callbacks. Wenn ein Ereignis in einem Quellsystem auftritt (z. B. ein neuer Commit, eine erfolgreiche Zahlung), sendet es eine HTTP-POST-Anfrage an eine von Ihnen bereitgestellte URL. Im Gegensatz zum Polling übertragen Webhooks Daten nahezu in Echtzeit, was Latenz und Serverlast reduziert. Dieses Push-Modell bringt jedoch Herausforderungen mit sich: die Authentizität zu überprüfen und Zustellungsfehler zu behandeln.
Warum signierte Payloads wichtig sind
Jeder kann eine HTTP-Anfrage an Ihren Endpunkt senden. Ohne Verifizierung könnten Angreifer Ereignisse fälschen und unbefugte Aktionen auslösen. Signierte Payloads lösen dieses Problem, indem sie eine kryptografische Signatur enthalten, die über den Anfrage-Body mit einem gemeinsamen Geheimnis berechnet wird. Der Empfänger berechnet die Signatur neu und vergleicht sie, um sicherzustellen, dass der Payload unverändert ist und vom erwarteten Absender stammt.
Wie HMAC-Signaturen funktionieren
Die meisten Dienste verwenden HMAC-SHA256. Der Absender erstellt eine Signatur, indem er den Payload mit einem geheimen Schlüssel hasht, und fügt sie in einen Header ein (z. B. X-Signature). Der Empfänger macht dasselbe und vergleicht die Signaturen mit einer zeitkonstanten Funktion, um Timing-Angriffe zu verhindern.
Schritt für Schritt: Verifizierung eines signierten Payloads
- Extrahieren Sie die Signatur aus dem Header (z. B.
X-Signature). - Holen Sie sich den rohen Anfrage-Body als String oder Buffer – parsen Sie ihn nicht zuerst, da Formatänderungen die Signatur brechen.
- Berechnen Sie die erwartete Signatur mit HMAC-SHA256 und Ihrem geheimen Schlüssel.
- Vergleichen Sie die Signaturen mit einer zeitkonstanten Vergleichsfunktion.
- Lehnen Sie die Anfrage ab mit HTTP 401, wenn sie nicht übereinstimmen.
Hier ist ein Node.js-Beispiel mit Express:
const crypto = require('crypto');
const express = require('express');
const app = express();
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-signature'];
const secret = process.env.WEBHOOK_SECRET;
const payload = req.body; // raw buffer
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
return res.status(401).send('Invalid signature');
}
// Process the event
const event = JSON.parse(payload);
// ... handle event
res.status(200).send('OK');
});
Hinweis: Verwenden Sie für die Verifizierung immer den rohen Body. Middleware, die JSON parst, verändert den Payload und führt zu Signaturabweichungen.
Entwurf einer Retry-Strategie
Selbst mit signierten Payloads können Netzwerkprobleme oder Serverausfälle zu Zustellungsfehlern führen. Eine robuste Retry-Strategie stellt sicher, dass Ereignisse nicht verloren gehen. Wichtige Überlegungen:
1. Schnell bestätigen
Antworten Sie mit einem 2xx-Status, sobald Sie die Signatur validiert und das Ereignis zur Verarbeitung in die Warteschlange gestellt haben. Dies verhindert, dass der Absender in einen Timeout läuft und unnötig erneut versucht.
2. Idempotenz
Wiederholungsversuche können dasselbe Ereignis mehrmals zustellen. Verwenden Sie einen Idempotenzschlüssel (oft im Payload oder in den Headern enthalten), um Duplikate zu vermeiden. Speichern Sie verarbeitete Ereignis-IDs und ignorieren Sie Duplikate.
3. Exponentielles Backoff mit Jitter
Wenn Ihr Endpunkt einen Fehler zurückgibt (nicht 2xx), sollte der Absender mit zunehmenden Verzögerungen erneut versuchen. Exponentielles Backoff (z. B. 1s, 2s, 4s, 8s) reduziert die Last während Ausfällen. Das Hinzufügen von zufälligem Jitter verhindert Thundering-Herd-Probleme.
Typischer Wiederholungsplan:
| Versuch | Verzögerung |
|---|---|
| 1 | Sofort |
| 2 | 1 Minute |
| 3 | 5 Minuten |
| 4 | 30 Minuten |
| 5 | 2 Stunden |
4. Dead Letter Queue
Nach maximalen Wiederholungsversuchen verschieben Sie das Ereignis in eine Dead Letter Queue zur manuellen Überprüfung. Dies verhindert endlose Wiederholungen und Datenverlust.
5. Überwachung und Warnmeldungen
Verfolgen Sie Zustellungserfolgsraten, Latenz und Fehlerursachen. Richten Sie Warnmeldungen für Fehlerspitzen ein, um Probleme frühzeitig zu erkennen.
Häufige Fallstricke und Best Practices
- Verifizieren Sie immer Signaturen – vertrauen Sie eingehenden Daten niemals blind.
- Verwenden Sie HTTPS, um Payloads während der Übertragung zu schützen.
- Rotieren Sie Geheimnisse regelmäßig und unterstützen Sie mehrere aktive Geheimnisse während der Rotation.
- Protokollieren Sie Webhook-Ereignisse (mit redigierten sensiblen Daten) zum Debuggen.
- Testen Sie mit Beispiel-Payloads mithilfe von Tools, die Webhook-Zustellungen simulieren.
FAQ
Was ist ein signierter Payload in Webhooks?
Ein signierter Payload enthält eine kryptografische Signatur (normalerweise HMAC), die es dem Empfänger ermöglicht, die Authentizität und Integrität der Anfrage zu überprüfen.
Wie oft sollte ein Webhook wiederholt werden?
Es gibt keine feste Anzahl; gängige Praktiken reichen von 3 bis 10 Wiederholungen mit exponentiellem Backoff. Danach werden Ereignisse oft an eine Dead Letter Queue gesendet.
Kann ich Webhooks ohne Signaturen verwenden?
Es ist möglich, aber stark abzuraten. Ohne Signaturen ist Ihr Endpunkt anfällig für gefälschte Anfragen und Datenlecks.
Bereit, Ihre Webhook-Payloads zu testen? Verwenden Sie unseren JSON Formatter, um JSON-Payloads schnell zu inspizieren und zu validieren.