Webhooks erklärt: Signierte Payloads und Retries

Backend2026-10-22TryQuickToolBox

Sie haben einen Webhook-Endpunkt erstellt, um Ereignisse von einem Drittanbieterdienst zu empfangen. Im Test funktioniert alles, aber in der Produktion stellen Sie doppelte Ereignisse, verpasste Benachrichtigungen und gelegentliche Sicherheitsbedenken hinsichtlich gefälschter Anfragen fest. Dies sind häufige Fallstricke bei der Implementierung von Webhooks ohne geeignete Schutzmaßnahmen.

Webhooks sind HTTP-Callbacks, mit denen Dienste Ihre Anwendung benachrichtigen, wenn etwas passiert. Im Gegensatz zum Polling bieten sie Echtzeit-Updates. Um sie zuverlässig zu nutzen, müssen Sie zwei kritische Aspekte berücksichtigen: Authentizität (Sicherstellung, dass die Anfrage vom erwarteten Absender stammt) und Zustellung (Umgang mit Fehlern und Wiederholungen). Dieser Artikel erklärt beide mit praktischen Codebeispielen.

Wie Webhooks funktionieren

Ein Webhook ist ein benutzerdefinierter HTTP-POST-Endpunkt. Wenn ein Ereignis eintritt, sendet der Quellendienst eine Anfrage an diese URL mit einer Payload, die das Ereignis beschreibt. Beispielsweise könnte ein Zahlungsabwickler einen Webhook senden, wenn eine Belastung erfolgreich ist.

Der Ablauf ist einfach:

  1. Sie registrieren eine Webhook-URL beim Dienst.
  2. Der Dienst sendet einen HTTP-POST an diese URL, wenn ein Ereignis ausgelöst wird.
  3. Ihr Endpunkt verarbeitet die Payload und gibt einen 2xx-Status zurück, um den Empfang zu bestätigen.

Ohne ordnungsgemäße Verifizierung kann jeder Anfragen an Ihren Endpunkt senden. Ohne Retry-Handling können vorübergehende Fehler zu verlorenen Ereignissen führen. Packen wir beides an.

Webhooks mit signierten Payloads absichern

Um sicherzustellen, dass ein Webhook vom erwarteten Absender stammt, signieren Dienste die Payload mit einem gemeinsamen Secret. Die Signatur ist typischerweise ein HMAC (Hash-based Message Authentication Code) des Request-Bodys, der in einem Header wie X-Signature gesendet wird.

So funktioniert HMAC-Signierung

Der Absender berechnet einen HMAC mit einem geheimen Schlüssel und dem rohen Request-Body und fügt dann die hex-kodierte Signatur in einen Header ein. Ihr Endpunkt berechnet den HMAC mit demselben Secret neu und vergleicht ihn mit der empfangenen Signatur. Wenn sie übereinstimmen, ist die Anfrage authentisch.

Hier ist ein minimales Beispiel in Node.js mit Express:

const crypto = require('crypto');
const express = require('express');
const app = express();

// Use raw body for signature verification
app.use(express.raw({ type: 'application/json' }));

app.post('/webhook', (req, res) => {
  const signature = req.headers['x-signature'];
  const secret = process.env.WEBHOOK_SECRET;
  const payload = req.body;

  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');
});

Wichtige Punkte:

Zusätzliche Sicherheitsmaßnahmen

Zuverlässige Wiederholungen implementieren

Die Webhook-Zustellung ist nicht garantiert. Netzwerke fallen aus, Ihr Server könnte nicht erreichbar sein oder Sie geben einen Nicht-2xx-Status zurück. Um dies zu handhaben, wiederholen Absender typischerweise mit exponentiellem Backoff. Als Empfänger müssen Sie Ihren Endpunkt so gestalten, dass er idempotent ist und schnell antwortet.

Auf der Absenderseite (wenn Sie Webhooks senden)

Wenn Sie einen Dienst erstellen, der Webhooks sendet, implementieren Sie Wiederholungen mit Backoff. Eine gängige Strategie:

Beispiel für Retry-Logik in Python:

import time
import requests
from requests.exceptions import RequestException

def send_webhook(url, payload, max_retries=5):
    for attempt in range(max_retries):
        try:
            response = requests.post(url, json=payload, timeout=5)
            if 200 <= response.status_code < 300:
                return True
            elif 400 <= response.status_code < 500 and response.status_code != 429:
                # Client error, don't retry
                return False
        except RequestException:
            pass
        # Exponential backoff with jitter
        delay = (2 ** attempt) + random.uniform(0, 1)
        time.sleep(delay)
    return False

Auf der Empfängerseite

Ihr Endpunkt sollte:

Idempotenz-Beispiel mit einer eindeutigen Datenbankeinschränkung:

CREATE TABLE processed_events (
  event_id VARCHAR(255) PRIMARY KEY,
  processed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Versuchen Sie vor der Verarbeitung, die Ereignis-ID einzufügen. Wenn sie den Primärschlüssel verletzt, überspringen Sie die Verarbeitung.

Webhooks lokal testen

Während der Entwicklung benötigen Sie eine öffentliche URL, damit der Dienst Ihren lokalen Server erreichen kann. Tools wie ngrok oder localtunnel machen Ihren localhost verfügbar. Verwenden Sie immer Test-Secrets und verifizieren Sie Signaturen in der Entwicklung, um Probleme frühzeitig zu erkennen.

Vergleich: Polling vs. Webhooks

Aspekt Polling Webhooks
Latenz Abhängig vom Intervall Nahezu Echtzeit
Serverlast Hoch (häufige Anfragen) Niedrig (nur bei Ereignissen)
Komplexität Einfach zu implementieren Erfordert Signaturverifizierung und Retry-Handling
Zuverlässigkeit Sie kontrollieren Wiederholungen Abhängig von der Retry-Richtlinie des Absenders

FAQ

Was ist eine signierte Webhook-Payload?

Eine signierte Payload enthält eine kryptografische Signatur (normalerweise HMAC), die mit einem gemeinsamen Secret generiert wird. Sie ermöglicht dem Empfänger zu überprüfen, dass die Anfrage vom erwarteten Absender stammt und nicht manipuliert wurde.

Wie gehe ich mit doppelten Webhook-Zustellungen um?

Machen Sie Ihren Endpunkt idempotent, indem Sie eine eindeutige Ereignis-ID aus der Payload verwenden. Speichern Sie verarbeitete IDs und ignorieren Sie Duplikate. Dadurch wird sichergestellt, dass Wiederholungen oder Netzwerkprobleme keine doppelte Verarbeitung verursachen.

Sollte ich fehlgeschlagene Webhook-Zustellungen wiederholen?

Ja, aber nur bei vorübergehenden Fehlern (Netzwerkprobleme, 5xx). Verwenden Sie exponentielles Backoff mit Jitter und legen Sie ein maximales Wiederholungslimit fest. Vermeiden Sie Wiederholungen bei 4xx-Fehlern (außer 429), da diese auf ein Problem mit der Anfrage selbst hinweisen.

Beim Debuggen von Webhook-Payloads müssen Sie oft JSON-Daten inspizieren. Der JSON Formatter kann Ihnen helfen, JSON-Payloads schnell übersichtlich zu formatieren und zu validieren.