<?php
namespace App\EventListener;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityManager;
use Psr\Log\LoggerInterface;
use App\Entity\Auth\LoginAttempt;
use App\Entity\User;
use App\Repository\Auth\LoginAttemptRepository;
use App\Service\Auth\LoginAttemptService;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Event\AuthenticationEvent;
use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
/**
* Class AuthenticationListener
* @see https://www.nomisoft.co.uk/articles/symfony-fail2ban-ip-blocking
* @see https://packagist.org/packages/anyx/login-gate-bundle#0.5
*/
class AuthenticationListener // implements AuthenticationSuccessHandlerInterface, AuthenticationFailureHandlerInterface
{
/** @var null|ContainerInterface */
private $container = null;
/**
* @var EntityManagerInterface
*/
private $em;
/**
* @var LoggerInterface
*/
private $logger;
/**
* @var RequestStack
*/
private $requestStack;
/**
* @var Request
*/
private $request;
/**
* @var LoginAttemptService
*/
private $loginAttemptService;
private $token;
/**
* @param ContainerInterface $container
* @param EntityManagerInterface $em
* @param LoggerInterface $logger
* @param RequestStack $request
*/
public function __construct(ContainerInterface $container, EntityManagerInterface $em, RequestStack $requestStack, LoggerInterface $logger, LoginAttemptService $loginAttemptService)
{
$this->container = $container;
$this->em = $em;
$this->requestStack = $requestStack;
$this->request = $requestStack->getCurrentRequest();
$this->logger = $logger;
$this->loginAttemptService = $loginAttemptService;
}
public function onSecurityInteractiveLogin(InteractiveLoginEvent $event)
{
$this->token = $event->getAuthenticationToken();
// $request = $event->getRequest();
// $this->onAuthenticationSuccess($request, $token);
// $this->onAuthenticationFailure($request, null);
$canLogin = $this->loginAttemptService->canLogin($this->request);
// dump(@compact('canLogin'));
$this->logger->info(sprintf("canLogin = %d", $canLogin));
}
public function onAuthenticationSuccess(AuthenticationEvent $event) // , Request $request, TokenInterface $token
{
$this->token = $event->getAuthenticationToken();
if ($this->token && $this->token->getUser() instanceof UserInterface) {
$loginAttempt = new LoginAttempt();
$loginAttempt->setUser($this->token->getUser());
$loginAttempt->setIpAddress($this->request->getClientIp());
$loginAttempt->setUsername($this->request->get('_username'));
$this->em->persist($loginAttempt);
$this->em->flush();
// $this->loginAttemptService->clearCountAttempts($this->request, $this->token->getUser());
$this->loginAttemptService->clearCountAttempts($this->request, $this->token->getUser()->getUsername());
return new RedirectResponse($this->container->get('router')->generate('home_page'));
}
if ($this->request->headers->get('referer')) {
return new RedirectResponse($this->request->headers->get('referer'));
}
return new RedirectResponse($this->container->get('router')->generate('app_login'));
}
/**
* {@inheritdoc}
*/
public function onAuthenticationFailure(AuthenticationFailureEvent $event) // Request $request, AuthenticationException $exception
{
$exception = $event->getAuthenticationException();
$data = [
'exception' => $exception->getMessage(),
'clientIp' => $this->request->getClientIp(),
'sessionId' => $this->request->getSession()->getId()
];
$ipAddress = $this->request->getClientIp();
$this->logger->error('Authentication failed for IP: ' . $ipAddress);
$this->loginAttemptService->addAttemptByUsername($this->request->get('_username')== null ?"" : $this->request->get('_username'), $data);
return new RedirectResponse($this->container->get('router')->generate('app_login'));
}
}