✨ feat(security): Ajoute LoginFormAuthenticator et configure la sécurité.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
when@dev:
|
||||
when@prod:
|
||||
sentry:
|
||||
dsn: '%env(SENTRY_DSN)%'
|
||||
options:
|
||||
|
||||
98
src/Security/LoginFormAuthenticator.php
Normal file
98
src/Security/LoginFormAuthenticator.php
Normal 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user