Webhooks erklärt: Signierte Payloads und Retries

Backend2026-10-18TryQuickToolBox

Sie haben eine API gebaut und müssen nun andere Dienste benachrichtigen, wenn Ereignisse eintreten. Sie richten einen Webhook-Endpunkt ein, stellen aber bald fest, dass jeder gefälschte Payloads senden kann und dass Ereignisse für immer verloren gehen, wenn Ihr Server ausfällt. Dies ist eine häufige Falle: Webhooks sind konzeptionell einfach, erfordern aber ein sorgfältiges Design in Bezug auf Sicherheit und Zuverlässigkeit.

In dieser Anleitung gehen wir auf die Grundlagen von Webhooks ein: wie man Payloads signiert, um Manipulation zu verhindern, wie man Signaturen auf der Empfängerseite überprüft und wie man Retry-Logik mit exponentiellem Backoff implementiert, um Fehler zu behandeln. Wir behandeln auch Idempotenz, um doppelte Verarbeitung zu vermeiden. Am Ende verfügen Sie über ein robustes Webhook-System, dem Sie vertrauen können.

Was sind Webhooks?

Webhooks sind benutzerdefinierte HTTP-Callbacks. Wenn ein Ereignis in einem Quellsystem auftritt (z. B. eine Zahlung wird verarbeitet), sendet es eine HTTP-POST-Anfrage an eine von Ihnen angegebene URL, mit einem Payload, der Ereignisdetails enthält. Dies ermöglicht Echtzeitkommunikation zwischen Diensten ohne Polling.

Webhooks bringen jedoch zwei Herausforderungen mit sich:

Webhooks mit signierten Payloads absichern

Um gefälschte Anfragen zu verhindern, sollte der Absender den Payload mit einem gemeinsamen Geheimnis signieren. Der Empfänger kann dann die Signatur überprüfen, um den Absender zu authentifizieren. Die gebräuchlichste Methode ist HMAC (Hash-based Message Authentication Code) mit SHA-256.

Wie HMAC-Signierung funktioniert

  1. Absender und Empfänger teilen einen geheimen Schlüssel (idealerweise eine lange, zufällige Zeichenkette).
  2. Für jeden Webhook berechnet der Absender einen HMAC des Request-Bodys mit dem Geheimnis und fügt ihn in einen Header ein (z. B. X-Signature).
  3. Der Empfänger berechnet denselben HMAC über den empfangenen Body und vergleicht ihn mit dem Header-Wert. Wenn sie übereinstimmen, ist die Anfrage authentisch.

Es ist entscheidend, den rohen Request-Body zu signieren, nicht eine geparste Version, um Abweichungen durch unterschiedliche JSON-Serialisierung zu vermeiden.

Beispiel: Signieren eines Payloads in Node.js

const crypto = require('crypto');

function signPayload(payload, secret) {
  return crypto.createHmac('sha256', secret).update(payload).digest('hex');
}

// Auf der Absenderseite:
const payload = JSON.stringify({ event: 'payment.success', amount: 100 });
const signature = signPayload(payload, 'your-secret-key');
// Signatur in Header einfügen: X-Signature: signature

Überprüfen der Signatur auf dem Empfänger

Auf der Empfängerseite müssen Sie die Signatur überprüfen, bevor Sie den Payload verarbeiten. Verwenden Sie einen Vergleich mit konstanter Zeit, um Timing-Angriffe zu verhindern.

const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const expected = crypto.createHmac('sha256', secret).update(payload).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

// In Ihrem Webhook-Endpunkt:
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-signature'];
  const payload = req.rawBody; // roher Body als String
  if (!verifySignature(payload, signature, 'your-secret-key')) {
    return res.status(401).send('Invalid signature');
  }
  // Ereignis verarbeiten
  res.status(200).send('OK');
});

Hinweis: Verwenden Sie immer HTTPS, um Man-in-the-Middle-Angriffe zu verhindern. Erwägen Sie außerdem, einen Zeitstempel in den signierten Payload aufzunehmen, um Replay-Angriffe zu verhindern.

Retries mit exponentiellem Backoff implementieren

Selbst mit einem zuverlässigen Empfänger können Netzwerkprobleme oder vorübergehende Ausfälle dazu führen, dass die Webhook-Zustellung fehlschlägt. Ein robuster Absender sollte fehlgeschlagene Zustellungen wiederholen. Naive Wiederholungen können jedoch den Empfänger überlasten oder doppelte Verarbeitung verursachen. Die Lösung: exponentielles Backoff mit Jitter und einer maximalen Wiederholungsgrenze.

Retry-Strategie

Beispiel: Retry-Logik in Node.js

async function deliverWebhook(url, payload, secret, maxRetries = 5) {
  const signature = signPayload(payload, secret);
  let attempt = 0;
  while (attempt < maxRetries) {
    try {
      const response = await fetch(url, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'X-Signature': signature },
        body: payload,
      });
      if (response.ok) return;
      throw new Error(`HTTP ${response.status}`);
    } catch (error) {
      attempt++;
      if (attempt >= maxRetries) throw error;
      const delay = Math.min(1000 * 2 ** attempt + Math.random() * 1000, 30000);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

Diese Funktion wiederholt bis zu 5 Mal mit exponentiellem Backoff und Jitter, wobei die Verzögerung auf 30 Sekunden begrenzt ist. Passen Sie die Parameter nach Ihren Anforderungen an.

Idempotenz sicherstellen

Wiederholungen können zu doppelten Zustellungen führen, daher muss Ihr Webhook-Handler idempotent sein. Fügen Sie eine eindeutige Ereignis-ID in den Payload ein und lassen Sie den Empfänger verarbeitete IDs verfolgen, um doppelte Verarbeitung zu vermeiden.

// Auf dem Empfänger:
const processedEvents = new Set();

app.post('/webhook', (req, res) => {
  const { id } = req.body;
  if (processedEvents.has(id)) {
    return res.status(200).send('Already processed');
  }
  // Ereignis verarbeiten
  processedEvents.add(id);
  res.status(200).send('OK');
});

Verwenden Sie in der Produktion einen persistenten Speicher (z. B. Redis oder eine Datenbank), um verarbeitete IDs über Neustarts hinweg zu verfolgen.

Vergleich: Signierte vs. unsignierte Webhooks

Aspekt Unsigniert Signiert (HMAC)
Sicherheit Jeder kann Anfragen fälschen Nur der Inhaber des Geheimnisses kann eine gültige Signatur erstellen
Integrität Payload kann manipuliert werden Manipulation macht die Signatur ungültig
Komplexität Gering Mittel (Schlüsselverwaltung, Verifizierung)
Anwendungsfall Interne, vertrauenswürdige Netzwerke Jeder öffentliche Webhook

FAQ

Was ist eine Webhook-Signatur?

Eine Webhook-Signatur ist ein kryptografischer Hash (normalerweise HMAC) des Payloads, der mit einem gemeinsamen Geheimnis erstellt wird. Sie ermöglicht es dem Empfänger zu überprüfen, dass die Anfrage vom erwarteten Absender stammt und dass der Payload nicht verändert wurde.

Wie oft sollte ich einen fehlgeschlagenen Webhook wiederholen?

Es gibt keine feste Anzahl, aber üblich sind 3 bis 5 Wiederholungen mit exponentiellem Backoff. Danach markieren Sie die Zustellung als fehlgeschlagen und benachrichtigen Ihr Team. Berücksichtigen Sie die Kritikalität des Ereignisses: Zahlungsbenachrichtigungen könnten mehr Wiederholungen rechtfertigen als unkritische Updates.

Kann ich Webhooks ohne HTTPS verwenden?

Sie sollten Webhooks in der Produktion niemals über einfaches HTTP verwenden. HTTPS verschlüsselt den Payload während der Übertragung und verhindert Abhören und Man-in-the-Middle-Angriffe. Selbst mit Signaturen werden bei HTTP sensible Daten offengelegt.

Bereit, Ihre Webhook-Payloads zu testen? Verwenden Sie unseren JSON Formatter, um JSON-Payloads vor dem Senden oder Debuggen übersichtlich zu formatieren und zu validieren.