如何在FOSUserBundle注销页面上获取用户详细信息?

时间:2017-06-22 10:18:04

标签: symfony fosuserbundle logout

我在FOSUserBundle webapp项目中使用Symfone 2.8。目前,用户在退出时只是被重定向到主页。这应该更改为“个人”注销页面,可以(可选)显示个人信息(例如即将进行的任务的提醒或简单的“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));
 }

1 个答案:

答案 0 :(得分: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'

对于logout事件,您可以创建一个这样的注销处理程序:

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中,这样你就可以从logout-page模板中获取它。