API-Reife: Scopes (read/write), Rate-Limit pro Key, OpenAPI-Spec
- ApiKey::hasScope + checkRateLimit (Fixed-Window/min via api_key_hits) - bootstrap erzwingt Rate-Limit (429) und api_require_scope() in Endpunkten - admin/api_keys.php: Scope-Auswahl + Limit beim Erstellen, Anzeige in Tabelle - api/openapi.php: OpenAPI-3.0-Spec (Import in Postman/Swagger) - Schema 0003 (api_keys.scope, api_keys.rate_limit, Tabelle api_key_hits)
This commit is contained in:
parent
ba121d60e6
commit
c7f9b7d39c
6 changed files with 146 additions and 4 deletions
|
|
@ -46,6 +46,38 @@ class ApiKey {
|
|||
return $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixed-Window-Rate-Limit pro Schlüssel (Anfragen/Minute). rate_limit = 0
|
||||
* bedeutet unbegrenzt. Gibt true zurück, wenn die Anfrage erlaubt ist.
|
||||
*/
|
||||
public static function checkRateLimit($row, $db) {
|
||||
$limit = (int)($row['rate_limit'] ?? 0);
|
||||
if ($limit <= 0) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
// alte Treffer (>60s) aufräumen
|
||||
$db->query("DELETE FROM api_key_hits WHERE api_key_id = ? AND hit_at < DATE_SUB(NOW(), INTERVAL 60 SECOND)", [$row['id']]);
|
||||
$cnt = $db->fetchOne("SELECT COUNT(*) AS c FROM api_key_hits WHERE api_key_id = ?", [$row['id']]);
|
||||
if ($cnt && (int)$cnt['c'] >= $limit) {
|
||||
return false;
|
||||
}
|
||||
$db->query("INSERT INTO api_key_hits (api_key_id) VALUES (?)", [$row['id']]);
|
||||
} catch (\Exception $e) {
|
||||
return true; // Bei Fehlern (z.B. Tabelle fehlt) nicht blockieren
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Prüft, ob der Schlüssel den geforderten Scope hat ('read' < 'write'). */
|
||||
public static function hasScope($row, $needed) {
|
||||
$scope = $row['scope'] ?? 'write';
|
||||
if ($needed === 'read') {
|
||||
return in_array($scope, ['read', 'write'], true);
|
||||
}
|
||||
return $scope === 'write';
|
||||
}
|
||||
|
||||
/** Liest den Schlüssel aus dem Request (Authorization: Bearer / X-API-Key). */
|
||||
public static function fromRequest() {
|
||||
$headers = [];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue