Skip to content

Sicherheit & Best Practices

Befolgen Sie diese Richtlinien, um eine sichere, zuverlässige und wartbare Integration mit dem iorder POS-System zu erstellen.

Immer HTTPS in der Produktion verwenden

Die iorder-API überträgt API-Schlüssel und Bestelldaten. Verwenden Sie in der Produktion immer HTTPS. Fallen Sie niemals auf HTTP zurück. Wenn Sie gegen eine Staging-Umgebung testen, die kein HTTPS verwendet, stellen Sie sicher, dass diese von Produktionsnetzwerken isoliert ist.

TLS in Ihrem HTTP-Client überprüfen:

bash
curl -v -H "api_key: abc123-def456-ghi789" \
  "https://{host}/orders/location"

Prüfen Sie, ob die Antwort SSL certificate verify ok oder eine entsprechende Meldung enthält.

API-Schlüssel sicher speichern

  • Hardcodieren Sie API-Schlüssel niemals im Quellcode, in Konfigurationsdateien, die versioniert werden, oder im clientseitigen Code.
  • Verwenden Sie Umgebungsvariablen oder einen Secrets Manager:
    bash
    export IORDER_API_KEY="abc123-def456-ghi789"
  • Verwenden Sie auf Kubernetes ein Kubernetes Secret.
  • Verwenden Sie auf Cloud-Plattformen den Secrets Manager der Plattform (AWS Secrets Manager, GCP Secret Manager, Azure Key Vault).
  • Injizieren Sie in CI/CD-Pipelines den API-Schlüssel zur Laufzeit, anstatt ihn in der Pipeline-Konfiguration zu speichern.

Beispiel: API-Schlüssel aus Umgebungsvariable laden (Node.js):

javascript
const apiKey = process.env.IORDER_API_KEY;
if (!apiKey) {
  throw new Error("IORDER_API_KEY environment variable is not set");
}

Beispiel: API-Schlüssel aus Umgebungsvariable laden (Java):

java
String apiKey = System.getenv("IORDER_API_KEY");
if (apiKey == null || apiKey.isBlank()) {
    throw new IllegalStateException("IORDER_API_KEY not set");
}

API-Schlüssel regelmäßig rotieren

  • Rotieren Sie API-Schlüssel in regelmäßigen Abständen (z. B. alle 90 Tage).
  • Aktualisieren Sie nach der Rotation Ihre Deployment-Konfiguration mit dem neuen Schlüssel.
  • Behalten Sie den alten Schlüssel während einer Übergangsperiode bei, um Ausfallzeiten zu vermeiden.
  • Wenn ein Schlüssel kompromittiert ist, rotieren Sie ihn sofort.

Alle Daten validieren

Obwohl die Integration Polling (nicht Webhooks) verwendet, sollten Sie dennoch alle Daten von der API als nicht vertrauenswürdig behandeln:

  • Validieren Sie, dass die API-Antwort gültiges JSON ist.
  • Validieren Sie, dass erforderliche Felder vorhanden sind und die erwarteten Typen haben.
  • Übergeben Sie rohe API-Daten nicht direkt in Datenbankabfragen (verwenden Sie parametrisierte Abfragen).
  • Validieren Sie Zeichenkettenlängen vor dem Speichern (z. B. Bestellkommentare, Produktnamen).
  • Bereinigen Sie Daten, bevor Sie sie in einer benutzerorientierten Oberfläche anzeigen.

Exponentiellen Backoff für Wiederholungen verwenden

Wenn die API einen 5xx-Fehler zurückgibt oder ein Netzwerkfehler auftritt, wiederholen Sie mit exponentiellem Backoff:

javascript
async function fetchWithRetry(url, options, maxRetries = 5) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);
      if (response.ok) return response;
      if (response.status < 500) throw new Error(`HTTP ${response.status}`); // 4xx nicht wiederholen
    } catch (err) {
      if (attempt === maxRetries - 1) throw err;
      const delay = Math.min(1000 * Math.pow(2, attempt), 30000);
      await new Promise(r => setTimeout(r, delay));
    }
  }
}
  • Minimaler Backoff: 1 Sekunde
  • Maximaler Backoff: 30-60 Sekunden
  • Jitter: Zufälligen Jitter hinzufügen, um den Thundering-Herd-Effekt zu vermeiden
  • Nur wiederholen bei: 5xx-Fehlern, Netzwerkfehlern, Timeouts
  • Nicht wiederholen bei: 4xx-Fehlern (außer 429, wenn Sie eine Ratenbegrenzung implementieren)

Idempotenz für Statusaktualisierungen implementieren

Der Endpunkt PUT /orders/{orderId}/statusupdate ist nicht idempotent. Um doppelte Aktualisierungen zu verhindern:

  • Führen Sie einen lokalen Satz oder eine Datenbanktabelle mit verarbeiteten Bestellnummern.
  • Prüfen Sie vor dem Senden einer Statusaktualisierung, ob Sie die Bestellung bereits verarbeitet haben.
  • Nach einer erfolgreichen Statusaktualisierung zeichnen Sie die Bestellnummer als verarbeitet auf.
  • Initialisieren Sie beim Anwendungsstart den verarbeiteten Satz aus Ihrer lokalen Persistenz.

Alle API-Interaktionen protokollieren

Protokollieren Sie jede API-Anfrage und -Antwort für Debugging und Prüfung:

javascript
function logApiCall(method, url, status, body) {
  console.log(JSON.stringify({
    timestamp: new Date().toISOString(),
    method,
    url,
    status,
    body: sanitize(body), // Sensible Daten vor dem Protokollieren entfernen
  }));
}

Was protokolliert werden sollte:

  • Anfragemethode, URL und Zeitstempel
  • Antwort-Statuscode
  • Antwort-Body (oder eine gekürzte Version)
  • Fehlerdetails bei Fehlern
  • SSE-Verbindungsereignisse (verbinden, trennen, wiederverbinden)

Was NICHT protokolliert werden sollte:

  • API-Schlüssel (maskieren: abc1****789)
  • Vollständige Kreditkartennummern oder Zahlungsdetails
  • Persönliche Daten über das Notwendige hinaus

SSE-Verbindungszustand überwachen

Der SSE-Stream ist das Herz Ihrer Integration. Überwachen Sie ihn genau:

  • Verfolgen Sie die Anzahl der SSE-Wiederverbindungen pro Stunde.
  • Alarmieren Sie, wenn Wiederverbindungen einen Schwellenwert überschreiten (z. B. mehr als 10 pro Stunde).
  • Verfolgen Sie die Zeit zwischen dem letzten Keepalive-Ereignis und einem Verbindungsabbruch.
  • Protokollieren Sie jede SSE-Verbindungszustandsänderung (verbunden, getrennt, Fehler).
  • Machen Sie in einer containerisierten Umgebung die SSE-Gesundheit als Prometheus-Metrik oder Health-Check-Endpunkt verfügbar.

Beispielmetrik:

text
# HELP iorder_sse_connection_status Aktueller SSE-Verbindungsstatus (1=verbunden, 0=getrennt)
# TYPE iorder_sse_connection_status gauge
iorder_sse_connection_status{location="Main Floor"} 1

# HELP iorder_sse_reconnects_total Gesamtzahl der SSE-Wiederverbindungen
# TYPE iorder_sse_reconnects_total counter
iorder_sse_reconnects_total{location="Main Floor"} 3

Netzwerk-Timeouts angemessen setzen

Setzen Sie explizite Timeouts für alle HTTP-Operationen:

OperationEmpfohlenes Timeout
Reguläre API-Aufrufe (GET, PUT, POST)30 Sekunden
SSE-Verbindung65+ Sekunden (muss länger als das Keepalive-Intervall sein)
DNS-Auflösung5 Sekunden
Verbindungsaufbau10 Sekunden

Beispiel (Node.js mit fetch):

javascript
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 30000);

try {
  const response = await fetch(url, {
    headers: { api_key: apiKey },
    signal: controller.signal,
  });
  // ...
} finally {
  clearTimeout(timeout);
}

Eigenes Polling selbst begrenzen

Auch wenn der Server derzeit keine Ratenbegrenzung erzwingt, sollten Sie sich selbst begrenzen:

  • SSE-gesteuertes Polling: Nur abrufen, wenn der SSE-Stream ein message-Ereignis sendet. Dies ist der primäre Polling-Auslöser.
  • Fallback-Intervall-Polling: In Intervallen von nicht weniger als 5 Sekunden als Sicherheitsnetz abrufen.
  • Keine Busy-Loops: Nie in einer engen Schleife abrufen (z. B. alle 100 ms). Der Server wird von mehreren Clients gemeinsam genutzt.

SSE-gesteuertes Polling gegenüber reinem Intervall-Polling bevorzugen

Das System ist für SSE-gesteuertes Polling ausgelegt. Reines Intervall-Polling:

  • Erhöht die Serverlast unnötig.
  • Verzögert die Bestellverarbeitung (Sie könnten kurz vor dem Eintreffen einer Bestellung abrufen und dann das gesamte Intervall warten).
  • Verschwendet Netzwerk- und Rechenressourcen.

Empfohlener Ansatz:

  1. Öffnen Sie eine persistente SSE-Verbindung.
  2. Rufen Sie sofort ab, wenn ein message-Ereignis eintrifft.
  3. Rufen Sie in einem 5-Sekunden-Intervall als Fallback ab (falls SSE-Nachrichten verpasst werden).
  4. Wenn die SSE-Verbindung nach einem Abbruch wiederhergestellt wird, setzen Sie das SSE-gesteuerte Polling fort und reduzieren Sie das Fallback-Polling.

Fehlerszenarien testen

Testen Sie Ihre Integration vor dem Deployment in der Produktion gegen diese Szenarien:

  • Ungültiger API-Schlüssel
  • Abgelaufener API-Schlüssel
  • Server-Neustart (SSE-Wiederverbindung)
  • Netzwerkunterbrechung (SSE-Wiederverbindung mit Offset)
  • Gleichzeitige Bestellverarbeitung (zwei Clients fragen denselben Standort ab)
  • Ungültige Zustandsübergänge
  • Große Payload (viele Bestellzeilen)
  • Langsames Netzwerk (Timeout-Behandlung)
  • Fehlende/Null-Felder in API-Antworten

Eine robuste Integration bewältigt all dies, ohne abzustürzen, Ressourcen zu verlieren oder Daten zu beschädigen.

Nächste Schritte

  • Lesen Sie das Kapitel Fehlerbehandlung für detaillierte Fehlerszenarien
  • Lesen Sie die Übersicht für den vollständigen Integrationsablauf