2016-07-26 1 views
2

모든 페이지로드 및 요청을 사용자 정의 감사 테이블에 기록하는 Symfony2 프로젝트에 감사 로깅을 추가하고 있습니다. 이 프로젝트는 Symfony2 (방문/로그 아웃)의 기본 로그 아웃 경로를 사용하여 세션을 파괴 한 다음/login 경로로 리디렉션합니다.Symfony2 로그 아웃 이벤트 리스너 이슈

onKernelRequest에 대해 설정된 이벤트 리스너가 올바른 데이터를 테이블에 씁니다. security.yml 파일에서 로그 아웃 경로에 대해 다음을 나열했습니다.

security: 
    firewalls: 
     main: 
      logout: 
       path: /logout 
       target: /login 

감사 로깅은 logout 이벤트를 제외한 모든 페이지에서 정상적으로 작동합니다. 로그 아웃 한 후 프로파일 러를 방문하여 사이드 바의 "마지막 10"옵션에서 '/ 로그 아웃'작업을 선택하려고했습니다. "Events"를 클릭하면 DebugHandler 및 ProfileListener와 같은 kernel.request의 기본 Symfony 이벤트가 나열되지만 사용자 정의 콜백은 "Not Listed Listeners"탭 아래에 표시됩니다.

security_yml 파일에 추가 할 수있는 success_handler가 있지만 세션이 삭제되기 전에 이벤트 수신기를 실행할 수있는 메서드가 필요합니다. Symfony가 로그 아웃을하기 전에 기존 리스너가 로그 아웃 이벤트를 기록하도록하는 방법이 있습니까?

나는 당신의 Audit logging 서비스에 명확하지 않다으로 편집

<?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 서비스에 LogoutHandlerInterface을 구현하는 LogoutHandler 서비스를 구현하고 Audit logging 서비스에 의존해야합니다.

로깅에서 무슨 일이 벌어지고 있는지 알게되면 분명히 알 수 있습니다.

<?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 

     } 

} 

구성 :

services: 
    appbundle_mylistener: 
     class: AppBundle\EventListener\MyListener 

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

편집 :

4

심포니의 로그 아웃 이벤트에 후크하는 가장 좋은 방법은,이 같은 LogoutHandlerInterface을 구현하기 위해

이벤트 리스너입니다

그래서 모두 y 사용자가 실제로해야 할 일은 AuditListener에서 logout 함수로 LogoutHandlerInterface을 구현 한 다음 handlers 매개 변수를 구성에 등록하십시오.