Symfony2:如何在控制器中手动注销用户?
我想在controller中执行类似操作以注销用户:Symfony2:如何在控制器中手动注销用户?,symfony,Symfony,我想在controller中执行类似操作以注销用户: $user = $this->get('security.context')->getToken()->getUser(); $user->logOut(); Symfony2中的注销由所谓的注销处理程序处理,它只是一个列表器,在URL与安全配置中的模式匹配时执行,即,如果URL是,比如说/Logout,则执行此侦听器。有两个内置注销处理程序: 它只会清除所有cookies 这会使会话无效 你所要做的就是和上一个一样
$user = $this->get('security.context')->getToken()->getUser();
$user->logOut();
Symfony2中的注销由所谓的注销处理程序处理,它只是一个列表器,在URL与安全配置中的模式匹配时执行,即,如果URL是,比如说
/Logout
,则执行此侦听器。有两个内置注销处理程序:
$this->get('security.context')->setToken(null);
$this->get('request')->getSession()->invalidate();
Symfony 2.6
$this->get('security.token\u storage')->setToken(null);
$this->get('request')->getSession()->invalidate();
警告
这仅在禁用功能时有效。在另一种情况下,用户将在下一个请求中通过“记住我”cookie再次登录
如果您使用的是记住ME功能,请考虑扩展的解决方案:
登录时,我们必须将用户设置为匿名用户。然后我们可以使用
$token->getUser()->getRoles()控制器中的code>或小枝模板中的{%if被授予('ROLE\u USER')%}
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
...
//$providerKey = $this->container->getParameter('fos_user.firewall_name');
$token = new AnonymousToken($providerKey, 'anon.');
$this->get('security.context')->setToken($token);
$this->get('request')->getSession()->invalidate();
使用户会话无效可能会导致一些不需要的结果。Symfony的防火墙有一个侦听器,它总是检查和刷新用户的令牌。您可以重定向到您在firewall.yml
(或security.yaml
)中指定的默认注销路径
在控制器中,您可以执行以下操作:
$this->redirect($this->generateUrl('your_logout_url'));
如果您不知道注销路径的名称(您的\u logout\u url
),可以使用以下命令从Symfony控制台获取该路径:
app/console router:match /logout
或更新的Symfony版本:
bin/console router:match /logout
:)如果您的站点启用了Memberme功能,您还应该清除Memberme cookie:
$this->get('security.context')->setToken(null);
$this->get('request')->getSession()->invalidate();
$response = new RedirectResponse($this->generateUrl('dn_send_me_the_bundle_confirm', array(
'token' => $token
)));
// Clearing the cookies.
$cookieNames = [
$this->container->getParameter('session.name'),
$this->container->getParameter('session.remember_me.name'),
];
foreach ($cookieNames as $cookieName) {
$response->headers->clearCookie($cookieName);
}
如果您使用的是symfony 4.x(我还没有测试过其他版本,所以它可能仍然可以工作),那么您可能需要使用symfony的内部注销处理程序(强烈推荐,因为它将以干净的方式为您处理所有事情,包括cookies和所有内容)。您也不需要为此编写太多代码,只需模拟注销请求即可:
... // Some code, that leads you to force logout the user
// Emulating logout request
$logoutPath = $this->container->get('router')->generate('app_logout');
$logoutRequest = Request::create($logoutPath);
$logoutResponse = $this->container->get('http_kernel')->handle($logoutRequest);
// User is logged out now
... // Stuff to do after logging out, eg returning response
这将使symfony执行请求-响应流,因此它将在内部调用注销处理程序。此方法允许您继续执行进一步的自定义代码。否则,如果在此处仅调用注销侦听器,则必须返回通常的注销响应,即现在在$logoutResponse
中的响应。或者,如果您想返回它,您还可以简单地:
return $logoutResponse;
在Symfony 4/5中,这仅足以删除用户:
/**
*@var TokenStorageInterface$token\u存储
*/
专用TokenStorageInterface$token_存储;
/**
*将强制从系统注销
*/
公共函数logoutCurrentlyLoggedInUser()
{
$this->token\u storage->setToken(null);
}
现在,您可以创建一个方法,稍后使用该方法检查用户是否已登录:
类应用程序扩展了AbstractController{。。。
/**
*返回当前登录的用户
*@return object | UserInterface | null
*/
公共函数getCurrentlyLoggedInUser()
{
返回$this->getUser();
}
您还应该将安全令牌设置为null:$this->get('security.context')->>setToken(null);$this->get('request')->getSession()->invalidate()
一定有一些事件可以触发,我不敢相信他们没有一种可靠的方法来保存区域设置并注销用户。注意:从2.4开始,像这样获取请求对象是不推荐的。将请求注入控制器或用户请求堆栈:SessionLogoutHandler可以作为服务访问:$this->get('security.logout.handler.session')->logout($request,$response,$token)
我已经用最新的Symfony 2.6尝试了这段代码,但没有效果。用户在重新加载页面后仍然登录。请给出建议。谢谢!如果您想防止用户在注销后被迫重新验证,这一点特别有用!在简单的情况下,提供程序密钥只是防火墙的名称(参见security.yml
)。我认为这个答案是最简单、最干净的。如果你想强制恶意用户注销,这只会导致重定向。恶意用户可以忽略302响应,继续进行恶意活动。假设他们在成功劫持会话后试图更改登录用户的密码。3 t输入错误密码的IME应该将其注销,但在这里,他们可以忽略302并尝试,除非您另外检查错误尝试的次数。底线:您不能强制这样注销。不知道为什么没有更多更新,clearcookie添加很有趣。(而且有效)因为它不起作用。将令牌设置为null并不能真正取消对用户的身份验证