<?php
namespace App\EventSubscriber;
use App\Entity\Log;
use App\Entity\SysUsers;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\AuthenticationEvents;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
/*use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;*/
use Symfony\Component\Security\Http\Event\LoginFailureEvent;
use Symfony\Component\Security\Core\Event\AuthenticationEvent;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\HttpFoundation\RequestStack;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
/**
* Subscribes to the following security events :
* - AuthenticationEvents::AUTHENTICATION_FAILURE
* - SecurityEvents::INTERACTIVE_LOGIN
*
* So it can log successful and failed login
* Some informations here: https://thisdata.com/blog/subscribing-to-symfonys-security-events/
*
* Class SecuritySubscriber
* @package App\EventSubscriber
*/
class SecuritySubscriber implements EventSubscriberInterface
{
private $entityManager;
private $tokenStorage;
private $authenticationUtils;
private $logger;
private $requestStack;
public function __construct(LoggerInterface $logger, EntityManagerInterface $entityManager, TokenStorageInterface $tokenStorage, AuthenticationUtils $authenticationUtils, RequestStack $requestStack)
{
$this->entityManager = $entityManager;
$this->tokenStorage = $tokenStorage;
$this->authenticationUtils = $authenticationUtils;
$this->logger = $logger;
$this->requestStack = $requestStack;
}
public static function getSubscribedEvents()
{
return array(
//AuthenticationEvents::AUTHENTICATION_FAILURE => 'onAuthenticationFailure',
SecurityEvents::INTERACTIVE_LOGIN => 'onSecurityInteractiveLogin',
);
}
public function onAuthenticationFailure( LoginFailureEvent $event )
{
$username = $this->authenticationUtils->getLastUsername();
$existingUser = $this->entityManager->getRepository(SysUsers::class)->findOneBy(['username' => $username]);
if ($existingUser) {
$message = "Log In Denied: Wrong password for User #" . $existingUser->getId() . " (" . $existingUser->getEmail() . ")";
$this->logger->error($message);
} else {
$message = "Log In Denied: User doesn't exist: " . $username;
$this->logger->error($message);
}
$this->addEntry($message, $username);
}
public function onSecurityInteractiveLogin( InteractiveLoginEvent $event )
{
$user = $this->tokenStorage->getToken()->getUser();
$message = "Log In Granted: User #" . $user->getId() . " (" . $user->getEmail() . ")";
$this->logger->info($message);
$this->addEntry($message, $user->getEmail());
}
private function addEntry($message, $username="")
{
$ip = $this->requestStack->getCurrentRequest()->getClientIp();
if($ip == 'unknown'){
$ip = $_SERVER['REMOTE_ADDR'];
}
$entry = new Log();
$entry->setIp($ip);
$entry->setUsername($username);
$entry->setMessage($message);
$this->entityManager->persist($entry);
$this->entityManager->flush();
}
}