Webhooks erklärt: Signierte Payloads und zuverlässige Wiederholungen
Sie haben gerade ein Zahlungs-Gateway eines Drittanbieters oder einen CI/CD-Dienst integriert und benötigen nun Echtzeit-Benachrichtigungen. Webhooks sind die Antwort – aber ohne ordnungsgemäße Sicherheit und Zuverlässigkeit können sie zur Frustrationsquelle werden. Angreifer können Anfragen fälschen, und Netzwerkstörungen können zu verpassten Ereignissen führen. In diesem Leitfaden zeigen wir Ihnen, wie Sie Webhooks mit signierten Payloads absichern und robuste Wiederholungsmechanismen implementieren.
Was sind Webhooks?
Webhooks sind benutzerdefinierte HTTP-Callbacks, die durch bestimmte Ereignisse ausgelöst werden. Wenn ein Ereignis eintritt (z. B. eine Zahlung erfolgreich ist), sendet der Quell Dienst eine HTTP-POST-Anfrage an eine von Ihnen angegebene URL, die Ereignisdaten enthält. Dieses Push-Modell ist effizienter als Polling und ermöglicht Echtzeit-Reaktionen.
Webhooks bringen jedoch zwei Herausforderungen mit sich: Authentizität (Sicherstellen, dass die Anfrage vom erwarteten Absender stammt) und Zuverlässigkeit (Sicherstellen, dass Sie keine Ereignisse verpassen).
Webhooks mit signierten Payloads absichern
Ein signierter Payload verwendet ein Geheimnis, das zwischen Sender und Empfänger geteilt wird, um eine kryptografische Signatur zu erstellen. Der Sender fügt diese Signatur in einen Header ein, und der Empfänger überprüft sie, um die Integrität und Herkunft des Payloads zu bestätigen.
Wie HMAC-Signierung funktioniert
HMAC (Hash-based Message Authentication Code) ist der Standardansatz. Der Sender berechnet einen HMAC über den Anfragetext unter Verwendung des geteilten Geheimnisses und fügt ihn in einen Header wie X-Signature ein. Der Empfänger berechnet den HMAC neu und vergleicht ihn.
// Beispiel: Generieren einer Signatur in Node.js
const crypto = require('crypto');
function generateSignature(payload, secret) {
return crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
}
// Auf der Empfängerseite überprüfen:
function verifySignature(payload, secret, receivedSignature) {
const expected = generateSignature(payload, secret);
// Verwenden Sie einen zeitkonstanten Vergleich, um Timing-Angriffe zu verhindern
return crypto.timingSafeEqual(
Buffer.from(expected, 'hex'),
Buffer.from(receivedSignature, 'hex')
);
}
Wichtige Punkte:
- Verwenden Sie immer ein starkes, eindeutiges Geheimnis pro Webhook-Endpunkt.
- Vergleichen Sie Signaturen mit einer zeitkonstanten Funktion, um Informationslecks zu vermeiden.
- Fügen Sie einen Zeitstempel in die Signatur ein, um Replay-Angriffe zu verhindern (z. B. signieren Sie
timestamp + payload).
Zusätzliche Sicherheitsmaßnahmen
- HTTPS: Verwenden Sie immer HTTPS, um Daten während der Übertragung zu verschlüsseln.
- IP-Allowlisting: Wenn der Anbieter IP-Bereiche veröffentlicht, beschränken Sie eingehende Anfragen auf diese IPs.
- Payload-Größenbeschränkungen: Lehnen Sie übermäßig große Payloads ab, um DoS zu mildern.
Zuverlässige Wiederholungen implementieren
Netzwerke sind unzuverlässig. Ein Webhook kann aufgrund von Timeouts, Serverfehlern oder vorübergehenden Ausfällen fehlschlagen. Eine robuste Wiederholungsstrategie stellt die eventuelle Zustellung sicher, ohne Ihr System oder den Sender zu überlasten.
Best Practices für Wiederholungen
- Exponentielles Backoff: Erhöhen Sie die Verzögerung zwischen Wiederholungen (z. B. 1s, 2s, 4s, 8s...).
- Maximale Wiederholungsgrenze: Begrenzen Sie die Anzahl der Versuche (z. B. 5), um Endlosschleifen zu vermeiden.
- Dead-Letter-Queue: Speichern Sie fehlgeschlagene Ereignisse nach erschöpften Wiederholungen zur manuellen Überprüfung.
- Idempotenz: Stellen Sie sicher, dass die mehrfache Verarbeitung desselben Ereignisses keine doppelten Nebenwirkungen verursacht.
Idempotenz in der Praxis
Fügen Sie eine eindeutige Ereignis-ID in den Payload ein. Verfolgen Sie auf der Empfängerseite verarbeitete IDs (in einer Datenbank oder einem Cache) und ignorieren Sie Duplikate. Zum Beispiel:
// Pseudocode für idempotente Verarbeitung
if (eventStore.exists(event.id)) {
return 200; // Bereits verarbeitet
}
// Ereignis verarbeiten...
eventStore.save(event.id);
Fehler elegant behandeln
Antworten Sie schnell mit einem 2xx-Status, um den Empfang zu bestätigen. Wenn die Verarbeitung Zeit in Anspruch nimmt, reihen Sie das Ereignis in eine Warteschlange ein und verarbeiten Sie es asynchron. Geben Sie 5xx nur bei vorübergehenden Fehlern zurück, die eine Wiederholung rechtfertigen; bei dauerhaften Fehlern (z. B. ungültiger Payload) geben Sie 4xx zurück, um vergebliche Wiederholungen zu verhindern.
Vergleich: Push vs. Poll
| Aspekt | Webhooks (Push) | Polling |
|---|---|---|
| Latenz | Nahezu Echtzeit | Abhängig vom Intervall |
| Effizienz | Sendet nur bei Ereignissen | Konstante Anfragen |
| Komplexität | Erfordert Wiederholungs-/Sicherheitslogik | Einfacher, aber verschwenderisch |
Testen Ihrer Webhook-Implementierung
Verwenden Sie Tools wie ngrok, um Ihren lokalen Server verfügbar zu machen und Webhook-Zustellungen zu simulieren. Überprüfen Sie die Signaturvalidierung und das Wiederholungsverhalten, indem Sie Anfragen absichtlich fehlschlagen lassen.
FAQ
Was ist ein signierter Webhook-Payload?
Ein signierter Payload enthält eine kryptografische Signatur (oft HMAC), die es dem Empfänger ermöglicht, die Authentizität und Integrität der Anfrage mithilfe eines geteilten Geheimnisses zu überprüfen.
Wie oft sollte ich einen fehlgeschlagenen Webhook wiederholen?
Es gibt keine universelle Zahl, aber 3–5 Wiederholungen mit exponentiellem Backoff sind üblich. Danach protokollieren Sie den Fehler zur manuellen Überprüfung.
Kann ich Webhooks ohne HTTPS verwenden?
Technisch ja, aber es ist höchst unsicher. Verwenden Sie immer HTTPS, um Abhören und Man-in-the-Middle-Angriffe zu verhindern.
Bereit, Webhook-Payloads zu inspizieren? Verwenden Sie unseren JSON-Formatter, um JSON-Payloads schnell zu verschönern und zu validieren.