src/EventSubscriber/LoginAttemptSubscriber.php line 37

Open in your IDE?
  1. <?php
  2. namespace App\EventSubscriber;
  3. use App\Entity\SsoUser;
  4. use Doctrine\ORM\EntityManagerInterface;
  5. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  6. use Symfony\Component\HttpFoundation\RequestStack;
  7. use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
  8. use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
  9. use Symfony\Component\Workflow\Registry;
  10. class LoginAttemptSubscriber implements EventSubscriberInterface
  11. {
  12.     private $requestStack;
  13.     private $workflows;
  14.     private $em;
  15.     private const MAX_ATTEMPTS 3;
  16.     public function __construct(RequestStack $requestStackRegistry $workflowsEntityManagerInterface $em)
  17.     {
  18.         $this->requestStack $requestStack;
  19.         $this->workflows $workflows;
  20.         $this->em $em;
  21.     }
  22.     public static function getSubscribedEvents(): array
  23.     {
  24.         return [
  25.             // En el sistema Guard (legacy), este es el evento de fallo
  26.             'security.authentication.failure' => 'onAuthenticationFailure',
  27.             // Este es el evento de éxito
  28.             'security.interactive_login' => 'onLoginSuccess',
  29.         ];
  30.     }
  31.     public function onAuthenticationFailure(AuthenticationFailureEvent $event): void
  32.     {
  33.         $session $this->requestStack->getSession();
  34.         $attempts $session->get('login_attempts'0) + 1;
  35.         $session->set('login_attempts'$attempts);
  36.         if ($attempts >= self::MAX_ATTEMPTS) {
  37.             // Como el Token está vacío, le pedimos el dato a la Request actual
  38.             $request $this->requestStack->getCurrentRequest();
  39.             
  40.             // Obtenemos el campo 'username' que viene del formulario POST
  41.             $username $request->request->get('username');
  42.             if ($username) {
  43.                 $user $this->em->getRepository(SsoUser::class)->findOneBy([
  44.                     'username' => $username
  45.                 ]);
  46.                 if ($user instanceof SsoUser) {
  47.                     $workflow $this->workflows->get($user'usuario');
  48.                     
  49.                     if ($workflow->can($user'bloquear')) {
  50.                         $workflow->apply($user'bloquear');
  51.                         $this->em->flush();
  52.                     }
  53.                 }
  54.             }
  55.         }
  56.     }
  57.     public function onLoginSuccess(InteractiveLoginEvent $event): void
  58.     {
  59.         // Si el login es correcto, reseteamos el contador de la sesión
  60.         $this->requestStack->getSession()->remove('login_attempts');
  61.     }
  62. }