src/AppBundle/Security/LoginLogServiceEventSubscriber.php line 35

Open in your IDE?
  1. <?php
  2. namespace AppBundle\Security;
  3. use AppBundle\Entity\AccessLog;
  4. use AppBundle\Entity\Customer;
  5. use AppBundle\Repository\AccessLogRepository;
  6. use AppBundle\Repository\CustomerRepository;
  7. use Doctrine\ORM\EntityManagerInterface;
  8. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  9. use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
  10. use Symfony\Component\Security\Http\Event\LoginFailureEvent;
  11. class LoginLogServiceEventSubscriber implements EventSubscriberInterface
  12. {
  13.     const TO_MANY_FAILURES 5;
  14.     public function __construct(
  15.         private EntityManagerInterface $entityManager,
  16.         private AccessLogRepository $accessLogRepository,
  17.         private CustomerRepository $customerRepository
  18.     ) {
  19.     }
  20.     public function onAuthenticationSuccess(InteractiveLoginEvent $event): void
  21.     {
  22.         $ip $_SERVER['REMOTE_ADDR'];
  23.         /** @var Customer */
  24.         $customer $event->getAuthenticationToken()->getUser();
  25.         $this->logLogin($ip$customer'success');
  26.         $this->setLastLoginOfCustomer($customer);
  27.     }
  28.     public function onAuthenticationFailure(LoginFailureEvent $event): void
  29.     {
  30.         $ip $_SERVER['REMOTE_ADDR'];
  31.         $customer $event?->getPassport()?->getUser();
  32.         $this->logLogin($ip$customer);
  33.         
  34.         $failures $this->getFailedLoginAttemptsByIp($_SERVER['REMOTE_ADDR']);
  35.         $this->slowDownResponseWhenToManyFailures($failures);
  36.     }
  37.     public static function getSubscribedEvents(): array
  38.     {
  39.         return [
  40.             LoginFailureEvent::class => 'onAuthenticationFailure',
  41.             InteractiveLoginEvent::class => 'onAuthenticationSuccess',
  42.         ];
  43.     }
  44.     private function setLastLoginOfCustomer(Customer $customer)
  45.     {
  46.         $customer->setLastLogin(new \DateTime(date('Y-m-d H:i:s')));
  47.         $customer->disableUpdateTimestamps();
  48.         $this->entityManager->persist($customer);
  49.         $this->entityManager->flush();
  50.     }
  51.     private function logLogin(string $ip, ?Customer $customerstring $type 'failure'): void
  52.     {
  53.         $accessLog = new AccessLog();
  54.         $accessLog->setCustomer($customer);
  55.         $accessLog->setType($type);
  56.         $accessLog->setCreated(new \DateTime(date('Y-m-d H:i:s')));
  57.         $accessLog->setIp($ip);
  58.         $this->entityManager->persist($accessLog);
  59.         $this->entityManager->flush();
  60.     }
  61.     
  62.     private function getFailedLoginAttemptsByIp(string $ip): int
  63.     {
  64.         return $this->accessLogRepository->findFailureQtyByIp($ip);
  65.     }
  66.     private function slowDownResponseWhenToManyFailures(int $failures): void
  67.     {
  68.         if ($failures self::TO_MANY_FAILURES) {
  69.             sleep(10);
  70.         }
  71.     }
  72. }