Files
breadcrumb-the-shire/docs/anfragelimits.md
fs 25370a1a55 add composer-unused, comprehensive docs, and project restructure
- Add icanhazstring/composer-unused as dev dependency for dependency hygiene checks
- Add German documentation (docs/) covering architecture, conventions, workflows, and developer checklists
- Add API layer (ApiAuth, ApiBootstrap, ApiResponse), audit, scheduler, custom fields, and SSO services
- Add Microsoft OIDC SSO, API token management, and user lifecycle features
- Add swagger-ui vendor integration and OpenAPI spec
- Add production Docker setup and bin/ scripts
- Update composer dependencies, config, templates, and frontend assets throughout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:27:35 +01:00

3.3 KiB

Anfragelimits (Rate Limiting)

Letzte Aktualisierung: 2026-02-21

Dieses Dokument beschreibt das aktuelle zentrale Rate-Limiting für Login und API.

Ziel

  • Brute-Force auf Login reduzieren.
  • API-Missbrauch (Burst/Spam) abfangen.
  • Einheitliches Verhalten mit 429 + Retry-After.

Technischer Aufbau

Storage

Tabelle: request_rate_limits

Spalten:

  • scope: Technischer Bereich (z. B. login.password.email_ip)
  • subject_hash: SHA-256 Hash des Subjects (keine Klartexte)
  • hits: Treffer im aktuellen Fenster
  • window_started_at: Beginn des aktuellen Zeitfensters (UTC)
  • blocked_until: Block-Ende (UTC), NULL wenn nicht geblockt

Schema:

  • Tabelle wird in db/init/init.sql mit angelegt.
  • Für Bestandsumgebungen sollte ein idempotentes SQL-Update bereitgestellt werden.

Service/Repository

  • Service: /lib/Service/Security/RateLimiterService.php
  • Repository: /lib/Repository/Security/RateLimitRepository.php

Der Service ist absichtlich fail-open:

  • Wenn DB/Storage fehlschlägt, wird kein harter Lock erzeugt.
  • Requests laufen weiter, um Verfügbarkeit nicht zu brechen.

API Rate Limiting

Integration:

  • /lib/Http/ApiBootstrap.php (vor Auth)

Aktuelle Limits:

  1. Bearer vorhanden (token + ip)
  • Scope: api.token_ip
  • Key: <selector>|<ip>
  • Limit: 300 Hits pro 60 Sekunden
  • Block: 120 Sekunden
  1. Kein Bearer (ip-only)
  • Scope: api.ip
  • Key: <ip>
  • Limit: 120 Hits pro 60 Sekunden
  • Block: 120 Sekunden

Bei überschreitung:

  • Response: 429
  • Body: {"error":"rate_limit_exceeded"}
  • Header: Retry-After: <sekunden>

Login Rate Limiting

Integration:

  • /pages/auth/login().php

Aktuelle Limits:

  1. Schritt resolve_email (IP)
  • Scope: login.resolve.ip
  • Key: <ip>
  • Limit: 25 Hits pro 600 Sekunden
  • Block: 300 Sekunden
  1. Schritt login_password (email + ip)
  • Scope: login.password.email_ip
  • Key: <lowercase-email>|<ip>
  • Limit: 5 Fehlversuche pro 900 Sekunden
  • Block: 900 Sekunden

Verhalten:

  • Bei Block: HTTP 429 + Retry-After.
  • UI zeigt generische Meldung: Too many login attempts. Please wait and try again.
  • Bei erfolgreichem Passwort-Login wird der Passwort-Scope für diesen Key zurückgesetzt.

Datenfluss pro Request

  1. Key bilden (scope + Subject)
  2. Subject hashen (sha256)
  3. Bestehenden Datensatz lesen
  4. Falls blocked_until > now: direkt blocken
  5. Fenster prüfen (window_started_at + windowSeconds)
  6. Hits erhöhen
  7. Bei hits > max: blocked_until = now + blockSeconds
  8. Ergebnis liefern (allowed, retry_after)

Operative Hinweise

  • Zeitbasis ist UTC (gmdate).
  • Tabelle kann wachsen; in V1 gibt es noch keinen automatischen Cleanup für alte Rate-Limit-Zeilen.
  • Bei Bedarf kann ein Wartungsjob alte/obsolete Zeilen periodisch löschen.

Smoke-Test (manuell)

API:

  1. Schnell >120 Requests/min ohne Bearer gegen /api/v1/*
  2. Erwartung: 429 mit Retry-After

Login:

  1. Mehrere falsche Passwortversuche für dieselbe Email+IP
  2. Erwartung nach 5 Fehlversuchen: 429 und Sperre für 15 Minuten

Erweiterungen (nächster Schritt)

  • Limits in Settings pflegbar machen (statt Hardcode).
  • Optional stricter Mode in Production (fail-closed nur für API).
  • Cleanup-Job für request_rate_limits.
  • Optional Logging/Stats für geblockte Requests (z. B. im Admin-Stats Modul).