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 ​

Stimmen Sie einen Wechselplan mit dem Betreiber ab und ersetzen Sie einen möglicherweise kompromittierten Schlüssel zeitnah. Folgen Sie dem Schlüsselwechsel: Ersatz für den richtigen Standort erzeugen, Client umstellen, Verarbeitung prüfen, alte Verbindungen beenden und alten Schlüssel löschen. Koordinieren Sie den Wechsel gegen doppelte Verarbeitung.

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 ​

Das folgende Beispiel begrenzt Wiederholungen für Leseanfragen. Klären Sie vor der Wiederholung einer Statusänderung oder Befehlsantwort nach Timeout oder 5xx, ob sie bereits erfolgreich war. Verwenden Sie diesen Wrapper nicht zum Wiederholen einer Kassenaktion.

javascript
async function fetchWithRetry(url, options) {
  const maxAttempts = 5;
  const initialDelay = 1000;
  const maxDelay = 30000;
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    let response;
    try {
      response = await fetch(url, options);
    } catch (error) {
      if (attempt === maxAttempts - 1) throw error;
    }
    if (response?.ok) return response;
    if (response && response.status < 500) {
      throw new Error(`HTTP ${response.status}`);
    }
    if (attempt === maxAttempts - 1) {
      throw new Error(`HTTP ${response.status}`);
    }
    const delay = Math.min(initialDelay * 2 ** attempt, maxDelay);
    await new Promise(resolve => setTimeout(resolve, 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 ​

Speichern Sie das Verarbeitungsergebnis dauerhaft, bevor Sie eine Bestellung gegenüber iorder bestätigen. Halten Sie Bestellnummern und Befehlskennungen getrennt und ordnen Sie sie Installation/Standort zu. Koordinieren Sie mehrere Worker vor der Übergabe an die Kasse.

Läuft eine Bestätigung in ein Timeout, kann der Vorgang bereits erfolgreich gewesen sein. Klären Sie das Ergebnis, statt die externe Bestellung erneut zu verarbeiten. Eine Statusänderung reserviert keine Arbeit; eine zweite Änderung wird nicht zwingend abgewiesen. Siehe wiederholte und gleichzeitige Aktualisierungen.

Alle API-Interaktionen protokollieren ​

Protokollieren Sie zur Fehlersuche Zeitstempel, Methode, Endpunktpfad ohne Zugangsdaten aus Query-Parametern, HTTP-Status, Dauer, Standort und die relevante Bestell- oder Befehlskennung. Erfassen Sie SSE-Verbindungswechsel und bereinigte Fehlerangaben.

Protokollieren Sie standardmäßig keine API-Schlüssel, rohen SSE-message-Nutzlasten, Zahlungsdetails oder vollständigen Anfrage-/Antwortbodys. Stimmen Sie erforderliche vorübergehende Nutzlastdiagnosen hinsichtlich Umfang, Zugriff, Bereinigung und Aufbewahrung mit dem Betreiber ab.

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-VerbindungLese-/Leerlaufschwelle, z. B. 60 Sekunden ohne Ereignis; nach Schließen erneut verbinden
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: Bei message sowie nach Verbindungsaufbau oder Wiederverbindung abrufen. Begrenztes Fallback-Polling zur Wiederherstellung verwenden.
  • 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 Zustandsnamen und wiederholte Bestätigungen
  • 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

Eine Deduplizierungsmenge im Arbeitsspeicher ist nur ein Beispiel. Speichern Sie Verarbeitungskennungen dauerhaft, wenn sie Neustarts überstehen müssen. Eine Statusbestätigung reserviert keine Bestellung für einen Integrationsclient.