feat(security): Ajoute LoginFormAuthenticator et configure la sécurité.

This commit is contained in:
Serreau Jovann
2025-11-22 21:28:08 +01:00
parent 58f45ce84c
commit 3902e4e637
3 changed files with 100 additions and 2 deletions

View File

@@ -24,7 +24,7 @@ security:
check_path: app_login # L'URL où le formulaire POST sera soumis
enable_csrf: true # Active la protection CSRF
csrf_token_id: authenticate # ID du jeton CSRF (doit correspondre à celui dans votre Twig)
entry_point: App\Security\LoginFormAuthenticator
logout:
path: app_logout # La route pour la déconnexion
target: app_login # Redirection après déconnexion réussie

View File

@@ -1,4 +1,4 @@
when@dev:
when@prod:
sentry:
dsn: '%env(SENTRY_DSN)%'
options:

View File

@@ -0,0 +1,98 @@
<?php
namespace App\Security;
use App\Entity\Account;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\SecurityBundle\Security; // L'objet moderne pour les opérations de sécurité
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
class LoginFormAuthenticator extends AbstractLoginFormAuthenticator
{
use TargetPathTrait;
public const LOGIN_ROUTE = 'app_login';
// Les propriétés typées sont la norme en Symfony 7 / PHP 8.2+
private EntityManagerInterface $entityManager;
private UrlGeneratorInterface $urlGenerator;
private Security $security;
public function __construct(EntityManagerInterface $entityManager, UrlGeneratorInterface $urlGenerator, Security $security)
{
$this->entityManager = $entityManager;
$this->urlGenerator = $urlGenerator;
$this->security = $security;
}
/**
* @param Request $request La requête HTTP entrante
* @return Passport Le passeport contenant l'utilisateur et les informations d'authentification
*/
public function authenticate(Request $request): Passport
{
$email = (string) $request->request->get('email', '');
$this->security->setLastUsername($request, $email);
return new Passport(
// 1. UserBadge: Charge l'utilisateur par l'email
new UserBadge($email, function(string $userIdentifier): Account {
$user = $this->entityManager->getRepository(Account::class)->findOneBy(['email' => $userIdentifier]);
if (!$user) {
throw new CustomUserMessageAuthenticationException('Email ou mot de passe invalide.');
}
return $user;
}),
// 2. Credentials: Vérifie le mot de passe
new PasswordCredentials($request->request->get('password', '')),
[
// 3. CsrfTokenBadge: Vérifie le jeton CSRF (l'ID 'authenticate' doit correspondre au Twig)
new CsrfTokenBadge('authenticate', $request->request->get('_csrf_token')),
// 4. RememberMeBadge: Ajoute le support du "Se souvenir de moi"
new RememberMeBadge(),
]
);
}
/**
* @param Request $request La requête actuelle
* @param TokenInterface $token Le jeton d'authentification
* @param string $firewallName Le nom du pare-feu utilisé ('main' dans votre cas)
* @return Response|null
*/
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
// 1. Redirige vers la cible originale si elle existe (avant la page de login)
if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {
return new RedirectResponse($targetPath);
}
// 2. Redirection par défaut (par exemple, vers le tableau de bord)
return new RedirectResponse($this->urlGenerator->generate('app_home'));
}
/**
* @param Request $request
* @return string L'URL de la page de connexion
*/
protected function getLoginUrl(Request $request): string
{
return $this->urlGenerator->generate(self::LOGIN_ROUTE);
}
}