2016-07-26 2 views
2

Я работаю над добавлением журнала аудита в проект 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 } 
+1

Можете ли вы предоставить свой собственный класс обратного вызова и его обслуживание? – Jeet

+0

Вам необходимо реализовать LogoutHandlerInterface и сообщить конфигурации, что у вас есть обработчик выхода из системы, см. Мой ответ ниже – Prof83

ответ

0

Как я не ясно, на вашем Audit logging службы, я думаю, это событие выхода из системы происходит, прежде чем руки. Следовательно, попробуйте позвонить в службу Audit logging, выполнив еще одну услугу LogoutHandler, которая реализует LogoutHandlerInterface и имеет зависимость от вашего сервиса Audit logging.

Мы можем получить четкое представление после того, как мы увидим, что происходит при регистрации.

4

Лучший способ вклиниться в случае выхода из системы Symfony является реализация LogoutHandlerInterface как это,

Event Listener:

<?php 

namespace AppBundle\EventListener; 

use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpFoundation\Response; 
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; 
use Symfony\Component\Security\Http\Logout\LogoutHandlerInterface; 

class MyListener implements LogoutHandlerInterface { 

    public function logout(Request $Request, Response $Response, TokenInterface $Token) { 

     // Your handling here 

     } 

} 

Config:

services: 
    appbundle_mylistener: 
     class: AppBundle\EventListener\MyListener 

security: 
    firewalls: 
     main: 
      logout: 
       handlers: [appbundle_mylistener] 

EDIT:

Итак, все y НУ действительно нужно сделать, это реализовать LogoutHandlerInterface от вашего AuditListener с функцией logout, а затем зарегистрировать параметр handlers в конфигурации