Я работаю над добавлением журнала аудита в проект Symfony2, который регистрирует все загрузки страниц и отправляет запросы в настраиваемую таблицу аудита. В проекте используется маршрут выхода по умолчанию для Symfony2 (посещение/выход из системы), который уничтожает сеанс, а затем перенаправляет его на маршрут/login.Symfony2 Logout Event Listener Issue
Для onKernelRequest установлен приемник событий, который затем записывает правильные данные в таблицу. В файле security.yml у меня есть список, указанный для маршрута выхода из системы.
security:
firewalls:
main:
logout:
path: /logout
target: /login
Ведение журнала аудита работает отлично для всех страниц, кроме события выхода из системы. После выхода из системы я попытался посетить профилировщик, а затем выбрать действие «/ logout» из опции «Последний 10» на боковой панели. При нажатии «События» в этом списке отображаются события Symfony по умолчанию для kernel.request, такие как DebugHandler и ProfileListener, однако мой пользовательский обратный вызов отображается на вкладке «Не вызываемые слушатели».
Существует файл success_handler, который может быть добавлен в файл security.yml, однако мне нужен метод, который может запускать мой прослушиватель событий до того, как сеанс будет уничтожен. Есть ли способ заставить существующего слушателя также записывать событие выхода из системы до того, как Symfony выполнит выход из системы?
Редактировать
<?php
// src/AuditBundle/EventListener/AuditListener.php
namespace AuditBundle\EventListener;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\RequestStack;
use AuditBundle\Entity\AuditLog;
class AuditListener
{
protected $requestStack;
protected $em;
protected $tokenStorage;
protected $authorizationChecker;
public function __construct(RequestStack $requestStack, \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage $tokenStorage, $authorizationChecker, \Doctrine\ORM\EntityManager $em = NULL)
{
$this->requestStack = $requestStack;
$this->em = $em;
$this->tokenStorage = $tokenStorage;
$this->authorizationChecker = $authorizationChecker;
}
public function onKernelRequest(GetResponseEvent $response)
{
$request = $response->getRequest();
if (strpos($request->getRequestUri(), 'fonts') !== false)
return;
if (strpos($request->getRequestUri(), 'css') !== false)
return;
if (strpos($request->getRequestUri(), '_wdt') !== false)
return;
if (strpos($request->getRequestUri(), 'js') !== false)
return;
if (strpos($request->getRequestUri(), '_profiler') !== false)
return;
$this->log('Request', $request);
}
public function postUpdate(\Doctrine\ORM\Event\LifecycleEventArgs $args)
{
$entity = $args->getEntity();
$this->em = $args->getEntityManager();
$className = $this->em->getClassMetadata(get_class($entity))->getName();
if ($entity instanceof \AuditBundle\Entity\AuditLog)
return;
$this->log($className.' Updated', $this->requestStack->getCurrentRequest(), $entity);
}
public function postPersist(\Doctrine\ORM\Event\LifecycleEventArgs $args)
{
$entity = $args->getEntity();
$this->em = $args->getEntityManager();
$className = $this->em->getClassMetadata(get_class($entity))->getName();
if ($entity instanceof \AuditBundle\Entity\AuditLog)
return;
$this->log($className.' Created', $this->requestStack->getCurrentRequest(), $entity);
}
public function postDelete(\Doctrine\ORM\Event\LifecycleEventArgs $args)
{
$entity = $args->getEntity();
$this->em = $args->getEntityManager();
$className = $this->em->getClassMetadata(get_class($entity))->getName();
if ($entity instanceof \AuditBundle\Entity\AuditLog)
return;
$this->log($className.' Deleted', $this->requestStack->getCurrentRequest());
}
protected function log($message, $request, $entity = NULL)
{
$log = new AuditLog();
$log->setType($request->getRealMethod());
if ($this->authorizationChecker->isGranted('IS_AUTHENTICATED_FULLY'))
{
$log->setUser($this->tokenStorage->getToken()->getUser());
}
if ($entity)
{
$log->setEntityId($entity->getId());
}
$log->setUriString($request->getRequestUri());
$log->setMessage($message);
$log->setDatetime(new \DateTime());
$log->setIp($request->getClientIp());
$log->setBrowser(isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '');
$this->em->persist($log);
$this->em->flush();
}
}
services.yml
services:
audits.audit_listener:
class: AuditBundle\EventListener\AuditListener
arguments: [@request_stack, @security.token_storage, @security.authorization_checker, @doctrine.orm.entity_manager]
tags:
- { name: kernel.event_listener, event: kernel.request }
Можете ли вы предоставить свой собственный класс обратного вызова и его обслуживание? – Jeet
Вам необходимо реализовать LogoutHandlerInterface и сообщить конфигурации, что у вас есть обработчик выхода из системы, см. Мой ответ ниже – Prof83