2016-07-26 32 views
2

私はすべてのページのロードと要求をカスタム監査テーブルに記録するSymfony2プロジェクトに監査ログを追加する作業を進めています。このプロジェクトではSymfony2(訪問/ログアウト)のデフォルトのログアウトルートが使用され、セッションが破棄されてから/ loginルートにリダイレクトされます。Symfony2ログアウトイベントリスナー問題

onKernelRequest用に設定されたイベントリスナーがあり、正しいデータがテーブルに書き込まれます。 security.ymlファイルには、ログアウトルートとして以下のものがあります。

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

ログアウトイベントを除くすべてのページで監査ログが正常に機能しています。ログアウトした後、私はプロファイラにアクセスして、サイドバーの "Last 10"オプションから '/ logout'アクションを選択してみました。 "Events"をクリックすると、DebugHandlerやProfileListenerなどのkernel.requestのデフォルトのSymfonyイベントがリストされますが、私のカスタムコールバックは "Not Listed Listeners"タブに表示されます。

security_ymlファイルに追加できるsuccess_handlerがありますが、セッションが破棄される前にイベントリスナーを実行できるメソッドが必要です。 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サービスに依存するサービスを試す必要があります。

ログに何が起きているのかが分かると、明確なアイデアが得られます。

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

EDIT

4

symfonyのログアウトイベントにフックするための最良の方法は、このようなLogoutHandlerInterfaceを実装するために

イベントリスナーである

だからすべてのy実際に行う必要がある場合は、AuditListenerからlogoutファンクションのLogoutHandlerInterfaceを実装し、handlersパラメータを設定に登録してください。

関連する問題