Webhooks erklärt: Signierte Payloads und Retry-Logik

Backend2026-10-15TryQuickToolBox

Sie haben gerade ein Zahlungs-Gateway integriert. Die Dokumentation besagt: "Wir senden einen Webhook, wenn eine Zahlung erfolgreich ist." Großartig. Aber dann fragen Sie sich: Woher weiß ich, dass die Anfrage wirklich von ihnen kam? Was, wenn mein Server down ist, wenn sie ihn senden? Was, wenn sie dasselbe Event zweimal senden?

Webhooks sind leistungsstark, aber mit Fallstricken verbunden. Dieser Leitfaden behandelt die Mechanik, Sicherheit und Zuverlässigkeitsmuster, die Sie benötigen, um sie korrekt zu handhaben.

Was ist ein Webhook?

Ein Webhook ist eine HTTP-POST-Anfrage, die ein System an ein anderes sendet, wenn ein bestimmtes Ereignis eintritt. Anstatt dass Ihre App alle paar Sekunden eine API abfragt ("Gibt es neue Bestellungen? Gibt es neue Bestellungen?"), pusht der Anbieter Daten zu Ihnen, sobald etwas passiert.

Typischer Ablauf:

  1. Sie registrieren eine URL (z. B. https://yourapp.com/webhooks/payments) beim Anbieter.
  2. Ein Ereignis tritt ein (Zahlung erfolgreich, Benutzer registriert, Datei hochgeladen).
  3. Der Anbieter sendet eine POST-Anfrage an Ihre URL mit einem JSON-Body, der das Ereignis beschreibt.
  4. Ihr Server verarbeitet das Ereignis und antwortet mit 2xx, um den Empfang zu bestätigen.

Wenn Sie nicht schnell antworten (normalerweise innerhalb von 5–30 Sekunden), betrachtet der Anbieter die Zustellung als fehlgeschlagen und versucht es möglicherweise erneut.

Warum Sie signierte Payloads verifizieren müssen

Ihr Webhook-Endpunkt ist öffentlich zugänglich. Jeder, der die URL entdeckt, kann gefälschte Ereignisse senden. Ohne Verifizierung könnte ein Angreifer ein "Zahlung erfolgreich"-Ereignis fälschen und kostenlose Waren erhalten.

Die Lösung: signierte Payloads. Der Anbieter berechnet eine kryptografische Signatur über den Request-Body unter Verwendung eines gemeinsamen Geheimnisses (nur Ihnen und ihm bekannt) und fügt sie in einen Header ein. Sie berechnen die Signatur auf Ihrer Seite neu und vergleichen sie.

Wie HMAC-Signierung funktioniert

Die meisten Anbieter verwenden HMAC-SHA256. Die Schritte:

  1. Der Anbieter verkettet den rohen Request-Body mit einem Zeitstempel (um Replay-Angriffe zu verhindern).
  2. Der Anbieter berechnet HMAC-SHA256(secret, timestamp + '.' + body).
  3. Der Anbieter sendet die Signatur in einem Header, z. B. X-Signature: t=1234567890,v1=abc123....
  4. Sie extrahieren den Zeitstempel und die Signatur, berechnen den HMAC mit Ihrer Kopie des Geheimnisses neu und vergleichen ihn mit einer zeitkonstanten Vergleichsfunktion.

Hier ist ein minimales Node.js-Beispiel:

const crypto = require('crypto');

function verifySignature(req, secret) {
  const signatureHeader = req.headers['x-signature'];
  const [tPart, vPart] = signatureHeader.split(',');
  const timestamp = tPart.split('=')[1];
  const receivedSig = vPart.split('=')[1];

  const payload = timestamp + '.' + JSON.stringify(req.body);
  const expectedSig = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  // Zeitkonstanter Vergleich zur Verhinderung von Timing-Angriffen
  return crypto.timingSafeEqual(
    Buffer.from(receivedSig, 'hex'),
    Buffer.from(expectedSig, 'hex')
  );
}

Wichtig: Verwenden Sie immer den rohen Request-Body für die Signaturverifizierung. Wenn Ihr Framework JSON parst und neu serialisiert, kann die Byte-Sequenz abweichen, was zu einem Verifizierungsfehler führt. Erfassen Sie den rohen Body vor dem Parsen.

Zeitstempel-Validierung

Überprüfen Sie, ob der Zeitstempel aktuell ist (z. B. innerhalb von 5 Minuten). Dies verhindert Replay-Angriffe, bei denen ein Angreifer eine gültige Anfrage abfängt und später erneut sendet.

Retry-Logik: Fehler elegant behandeln

Ihr Server könnte down, überlastet sein oder eine Netzwerkstörung haben. Anbieter handhaben dies, indem sie fehlgeschlagene Zustellungen erneut versuchen. Aber Sie müssen Ihren Endpunkt so gestalten, dass er Wiederholungsversuche sicher verarbeitet.

Exponentielles Backoff mit Jitter

Anbieter versuchen es typischerweise mit zunehmenden Verzögerungen erneut: 1 Minute, 5 Minuten, 30 Minuten, 2 Stunden usw. Dies wird als exponentielles Backoff bezeichnet. Einige fügen zufälligen Jitter hinzu, um Thundering-Herd-Probleme zu vermeiden.

Von Ihrer Seite aus kontrollieren Sie nicht den Wiederholungsplan des Anbieters, aber Sie sollten:

Idempotenz: Der Schlüssel zu sicheren Wiederholungsversuchen

Wiederholungsversuche bedeuten, dass Sie dasselbe Ereignis möglicherweise mehrmals empfangen. Ihre Verarbeitung muss idempotent sein – dasselbe Ereignis zweimal zu verarbeiten sollte die gleiche Wirkung haben wie einmal.

Üblicher Ansatz: Fügen Sie eine eindeutige Event-ID in die Payload ein. Prüfen Sie vor der Verarbeitung, ob Sie diese ID bereits behandelt haben. Wenn ja, geben Sie 200 zurück und überspringen Sie die Verarbeitung.

async function handleWebhook(event) {
  const existing = await db.events.findOne({ id: event.id });
  if (existing) {
    return { status: 200, body: 'Already processed' };
  }

  await db.events.insert({ id: event.id, processedAt: new Date() });
  await processEvent(event);
  return { status: 200, body: 'OK' };
}

Dieses Muster stellt sicher, dass Sie, selbst wenn der Anbieter das Ereignis dreimal sendet, nur einmal handeln.

Vergleich: Polling vs. Webhooks

Aspekt Polling Webhooks
Latenz Abhängig vom Intervall (z. B. 30s) Nahezu Echtzeit
Serverlast Konstant, auch wenn keine Ereignisse auftreten Nur wenn Ereignisse auftreten
Komplexität Einfach zu implementieren Erfordert Endpunkt, Verifizierung, Wiederholungsversuche
Zuverlässigkeit Sie kontrollieren Wiederholungsversuche Abhängig von der Wiederholungsrichtlinie des Anbieters

Webhooks gewinnen bei Echtzeit-Updates, aber Polling kann ein Fallback für kritische Ereignisse sein, wenn Sie besorgt über verpasste Zustellungen sind.

Checkliste für Best Practices

Debuggen von Webhook-Problemen

Wenn Webhooks fehlschlagen, ist der erste Schritt, die rohe Anfrage zu inspizieren. Häufige Probleme:

Wenn Sie HTTP-Traffic debuggen, können Tools wie Nginx Log Analyzer Ihnen helfen, Muster bei Anfragefehlern und Antwortcodes zu erkennen.

FAQ

Was ist ein Webhook-Secret und wie speichere ich es?

Das Secret ist ein gemeinsamer Schlüssel, der zum Signieren von Payloads verwendet wird. Speichern Sie es in Umgebungsvariablen oder einem Secrets Manager – niemals im Code oder in der Versionskontrolle. Rotieren Sie es regelmäßig, wenn der Anbieter dies unterstützt.

Wie oft wird ein Anbieter einen fehlgeschlagenen Webhook erneut versuchen?

Dies variiert je nach Anbieter. Einige versuchen es 24 Stunden lang mit exponentiellem Backoff erneut, andere 3 Tage. Überprüfen Sie die Dokumentation Ihres Anbieters für den genauen Zeitplan und die maximalen Versuche.

Kann ich Webhooks mit serverlosen Funktionen verwenden?

Ja, aber beachten Sie die Ausführungszeitlimits. Bestätigen Sie den Webhook schnell (geben Sie 200 zurück) und lagern Sie schwere Verarbeitung in eine Warteschlange oder Hintergrundfunktion aus, um Timeouts zu vermeiden.

Bereit, robuste Webhook-Integrationen zu erstellen? Beginnen Sie mit der Verifizierung von Signaturen und der Implementierung von Idempotenz – diese beiden Schritte sparen Ihnen Stunden beim Debuggen und verhindern kostspielige Sicherheitsvorfälle.