<?php
/**
* Created by PhpStorm.
* User: sbrun
* Date: 2018-03-19
* Time: 14:03
*/
namespace App\EventSubscriber;
use App\Entity\Log;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
/*use Symfony\Component\Translation\TranslatorInterface;*/
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* Subscribes to the KernelEvents::REQUEST events :
* So it can check for brute force attacks
* Class FirewallSubscriber
* @package App\EventSubscriber
*/
class FirewallSubscriber implements EventSubscriberInterface
{
private $request;
private $router;
private $entityManager;
private $authenticationUtils;
private $translator;
private $timeout;
private $max_login;
public function __construct(ContainerInterface $container, TranslatorInterface $translator, EntityManagerInterface $entityManager, AuthenticationUtils $authenticationUtils, RequestStack $requestStack, RouterInterface $router)
{
$this->request = $requestStack->getCurrentRequest();
$this->router = $router;
$this->entityManager = $entityManager;
$this->authenticationUtils = $authenticationUtils;
$this->translator = $translator;
$this->timeout = $container->getParameter('bruteforce_timeout');
$this->max_login = $container->getParameter('bruteforce_max_login');
}
public static function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => ['beforeFirewall', 10]
];
}
/**
* Check if there are too many connexion failures from the same ip within a defined time
* Only when on fos_user_security_check route and a POST request
*
* @param RequestEvent $event
*/
public function beforeFirewall(RequestEvent $event)
{
$request = $event->getRequest();
if ($request->isMethod(Request::METHOD_POST)) {
$routeInfos = $this->router->matchRequest($request);
if (isset($routeInfos['_route']) && $routeInfos['_route'] === 'fos_user_security_check') {
$username = $this->authenticationUtils->getLastUsername();
if ($this->entityManager->getRepository(Log::class)->checkBruteForce($username, $this->max_login, $this->timeout)) {
$minutes = date("i", $this->timeout);
throw new HttpException(
429,
$this->translator->transChoice(
'too.many.failed.authentication',
$minutes,
['%minutes%'=>$minutes],
'security'
)
);
}
}
}
}
}