Symfony2:如何在控制器中手动注销用户?

Symfony2:如何在控制器中手动注销用户?,symfony,Symfony,我想在controller中执行类似操作以注销用户: $user = $this->get('security.context')->getToken()->getUser(); $user->logOut(); Symfony2中的注销由所谓的注销处理程序处理,它只是一个列表器,在URL与安全配置中的模式匹配时执行,即,如果URL是,比如说/Logout,则执行此侦听器。有两个内置注销处理程序: 它只会清除所有cookies 这会使会话无效 你所要做的就是和上一个一样

我想在controller中执行类似操作以注销用户:

$user = $this->get('security.context')->getToken()->getUser();
$user->logOut();

Symfony2中的注销由所谓的注销处理程序处理,它只是一个列表器,在URL与安全配置中的模式匹配时执行,即,如果URL是,比如说
/Logout
,则执行此侦听器。有两个内置注销处理程序:

  • 它只会清除所有cookies
  • 这会使会话无效
  • 你所要做的就是和上一个一样。您只需调用以下命令即可实现:

    传统符号
    $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()或小枝模板中的
    {%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并不能真正取消对用户的身份验证