我在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));
}
答案 0 :(得分:1)
干净的方法是将用户的名称/数据保存在侦听security.interactive_logout
事件的 EventSubscriber / Listener 中的会话中。
由此产生的两个问题是:
LogoutHandler
您可以通过将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模板中获取它。