feat: auth system - login/logout/session with rate limiting
Dieser Commit ist enthalten in:
Ursprung
581888e142
Commit
1c59b667f2
2 geänderte Dateien mit 88 neuen und 0 gelöschten Zeilen
66
edu/api/auth.php
Normale Datei
66
edu/api/auth.php
Normale Datei
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
// /api/login, /api/logout, /api/me
|
||||
|
||||
if ($resource === 'login' && get_method() === 'POST') {
|
||||
$body = get_json_body();
|
||||
$username = trim($body['username'] ?? '');
|
||||
$password = $body['password'] ?? '';
|
||||
|
||||
if (!$username || !$password) {
|
||||
json_error('Benutzername und Passwort erforderlich');
|
||||
}
|
||||
|
||||
// Rate limiting via session
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
$key = 'login_attempts_' . $ip;
|
||||
$attempts = $_SESSION[$key] ?? ['count' => 0, 'first' => time()];
|
||||
if (time() - $attempts['first'] > 60) {
|
||||
$attempts = ['count' => 0, 'first' => time()];
|
||||
}
|
||||
if ($attempts['count'] >= 5) {
|
||||
json_error('Zu viele Anmeldeversuche. Bitte eine Minute warten.', 429);
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT id, username, password_hash, display_name, is_admin FROM users WHERE username = :u");
|
||||
$stmt->execute([':u' => $username]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
if (!$user || !password_verify($password, $user['password_hash'])) {
|
||||
$attempts['count']++;
|
||||
$_SESSION[$key] = $attempts;
|
||||
json_error('Benutzername oder Passwort falsch', 401);
|
||||
}
|
||||
|
||||
session_regenerate_id(true);
|
||||
$_SESSION['user_id'] = $user['id'];
|
||||
$_SESSION['is_admin'] = $user['is_admin'];
|
||||
unset($_SESSION[$key]);
|
||||
|
||||
json_ok(['user' => [
|
||||
'id' => $user['id'],
|
||||
'username' => $user['username'],
|
||||
'display_name' => $user['display_name'],
|
||||
'is_admin' => (bool) $user['is_admin']
|
||||
]]);
|
||||
}
|
||||
|
||||
if ($resource === 'logout' && get_method() === 'POST') {
|
||||
session_destroy();
|
||||
json_ok(['ok' => true]);
|
||||
}
|
||||
|
||||
if ($resource === 'me' && get_method() === 'GET') {
|
||||
$user_id = require_auth();
|
||||
$stmt = $pdo->prepare("SELECT id, username, display_name, is_admin FROM users WHERE id = :id");
|
||||
$stmt->execute([':id' => $user_id]);
|
||||
$user = $stmt->fetch();
|
||||
if (!$user) { session_destroy(); json_error('Benutzer nicht gefunden', 401); }
|
||||
json_ok(['user' => [
|
||||
'id' => $user['id'],
|
||||
'username' => $user['username'],
|
||||
'display_name' => $user['display_name'],
|
||||
'is_admin' => (bool) $user['is_admin']
|
||||
]]);
|
||||
}
|
||||
|
||||
json_error('Unbekannte Auth-Aktion', 404);
|
||||
Laden …
Tabelle hinzufügen
Einen Link hinzufügen
In neuem Issue referenzieren