【问题标题】:How to get user details on FOSUserBundle logout page?如何在 FOSUserBundle 注销页面上获取用户详细信息?
【发布时间】:2017-06-22 10:18:03
【问题描述】:

我在Symfone 2.8 webapp 项目中使用FOSUserBundle。目前,用户在注销时只是被重定向到主页。这应该更改为“个人”注销页面,该页面可以(可选)显示个人信息(例如,即将完成的任务的提醒或简单的“Goodbey USERNAME”,而不仅仅是“Goodbey”)...

所以我需要访问/使用当前注销用户的详细信息。但是由于用户刚刚注销,我不能再访问用户对象了吗?

如何解决?

这是我使用的配置:

// config
security:
    ...  
    providers:
        fos_userbundle:
            id: fos_user.user_provider.username_email

    firewalls:
        main:
            ...
            logout:
                path: fos_user_security_logout
                target: /logoutpage


 // route
 <route id="user_logout" path="/logoutpage" methods="GET">
    <default key="_controller">AppBundle:Default:logout</default>
 </route> 


 // Controller action
 public function logoutAction() {
    $loggedOutUser = HOW_TO_GET_USER(???);

    $template = 'AppBundle:Default:logout.html.twig';
    return $this->render($template, array('user' => $loggedOutUser));
 }

【问题讨论】:

    标签: symfony fosuserbundle logout


    【解决方案1】:

    干净的方法是将用户的姓名/数据保存在一个监听security.interactive_logout 事件的EventSubscriber/Listener 中的会话中。

    由此产生的两个问题是:

    • 默认LogoutHandler没有调度注销事件
    • symfony 根据默认配置在注销时清除会话

    您可以通过将invalidate_session 设置为false 来更改会话清除行为

    security:
      firewalls:
        main:
          # [..]
          logout:
             path: 'fos_user_security_logout'
             target: '/logoutpage'
             invalidate_session: false # <- do not clear the session
             handlers:
               - 'Namespace\Bridge\Symfony\Security\Handler\DispatchingLogoutHandler'
    

    对于注销事件,您可以像这样创建注销处理程序:

    class DispatchingLogoutHandler implements LogoutHandlerInterface
    {
        /** @var EventDispatcherInterface */
        protected $eventDispatcher;
    
        /**
         * @param EventDispatcherInterface $event_dispatcher
         */
        public function __construct(EventDispatcherInterface $event_dispatcher)
        {
            $this->eventDispatcher = $event_dispatcher;
        }
    
        /**
         * {@inheritdoc}
         */
        public function logout(Request $request, Response $response, TokenInterface $token)
        {
            $this->eventDispatcher->dispatch(
                SecurityExtraEvents::INTERACTIVE_LOGOUT,
                new InteractiveLogoutEvent($request, $response, $token)
            );
        }
    }
    

    添加一些服务配置(或使用自动装配):

      Namespace\Bridge\Symfony\Security\Handler\DispatchingLogoutHandler:
        class: 'Namespace\Bridge\Symfony\Security\Handler\DispatchingLogoutHandler'
        arguments:
          - '@event_dispatcher'
    

    事件类

    namespace Namespace\Bridge\Symfony;
    
    final class SecurityExtraEvents
    {
        /**
         * @Event("\Namespace\Bridge\Symfony\Security\Event\Logout\InteractiveLogoutEvent")
         */
        const INTERACTIVE_LOGOUT = 'security.interactive_logout';
    }
    

    事件本身:

    final class InteractiveLogoutEvent extends Event
    {
        /**
         * @var Request
         */
        protected $request;
    
        /**
         * @var Response
         */
        protected $response;
    
        /**
         * @var TokenInterface
         */
        protected $token;
    
        /**
         * @param Request $request
         * @param Response $response
         * @param TokenInterface $token
         */
        public function __construct(Request $request, Response $response, TokenInterface $token)
        {
            $this->request = $request;
            $this->response = $response;
            $this->token = $token;
        }
    
        /**
         * @return TokenInterface
         */
        public function getToken()
        {
            return $this->token;
        }
    
        /**
         * @return TokenInterface
         */
        public function getRequest()
        {
            return $this->token;
        }
    
        /**
         * @return Response
         */
        public function getResponse()
        {
            return $this->response;
        }
    
        /**
         * @return string
         */
        public function getName()
        {
            return SecurityExtraEvents::INTERACTIVE_LOGOUT;
        }
    }
    

    订阅者:

    class UserEventSubscriber implements EventSubscriberInterface
    {
        /** @var LoggerInterface */
        protected $logger;
    
        /** @param LoggerInterface $logger */
        public function __construct(LoggerInterface $logger)
        {
            // inject the session here
            $this->logger = $logger;
        }
    
        /**
         * {@inheritdoc}
         */
        public static function getSubscribedEvents()
        {
            return array(
                SecurityExtraEvents::INTERACTIVE_LOGOUT => 'onInteractiveLogout',
            );
        }
    
        /**
         * {@inheritdoc}
         */
        public function onInteractiveLogout(InteractiveLogoutEvent $event)
        {
    
            $user = $event->getToken()->getUser();
    
            // save the username in the session here
    
            $this->logger->info(
                'A User has logged out.',
                array(
                    'event' => SecurityExtraEvents::INTERACTIVE_LOGOUT,
                    'user'  => array(
                        'id'    => $user->getId(),
                        'email' => $user->getEmail(),
                    )
                )
            );
        }
    }
    

    通过使用kernel.event_subscriber 标记订阅者来启用它

      Namespace\EventSubscriber\UserEventSubscriber:
        class: 'Namespace\EventSubscriber\UserEventSubscriber'
        arguments: ['@monolog.logger.user']
        tags:
          - { name: 'kernel.event_subscriber' }
    

    简单吧?一个有点脏的解决方案是创建一个请求侦听器,将用户名保存在每个请求的 session-flashbag 中,以便您可以从那里在注销页面模板中获取它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-30
      • 1970-01-01
      • 1970-01-01
      • 2015-04-12
      相关资源
      最近更新 更多