currentUser() !== null) { $this->f3->reroute('@dashboard'); return; } $this->render('auth/login.html', ['pageTitle' => 'Connexion']); } public function login(): void { $this->verifyCsrf(); $username = trim((string) ($this->f3->get('POST.username') ?? '')); $password = (string) ($this->f3->get('POST.password') ?? ''); // User étend DB\SQL\Mapper — inutile de recréer un Mapper générique. // Le 3e argument du constructeur Auth est le callback de comparaison. $user = new User(); $auth = new \Auth($user, ['id' => 'username', 'pw' => 'password_hash'], 'password_verify'); if (!$auth->login($username, $password)) { usleep(1_500_000); // 1,5 s — ralentit le brute-force $this->flash('error', 'Identifiants invalides.'); $this->f3->reroute('@login'); return; } session_regenerate_id(true); // Prévient la fixation de session. $this->f3->set('SESSION.user_id', $user->id); $this->flash('success', 'Connexion réussie.'); $this->f3->reroute('@dashboard'); } public function logout(): void { $this->verifyCsrf(); $this->f3->clear('SESSION.user_id'); session_regenerate_id(true); // Invalide l'ancien ID de session. $this->flash('success', 'Déconnexion effectuée.'); $this->f3->reroute('@login'); } }