从Symfony2中的http_basic身份验证注销

时间:2015-03-24 09:24:30

标签: php security symfony basic-authentication logout

每当我转到/admin/logout时,我都被正确地重定向到我项目的根目录,但在我访问/admin/时仍然登录,因为我没有提示输入凭据。

这是我的配置:

security.yml

security:
    firewalls:
        admin_area:
            pattern:    ^/admin
            http_basic: ~
            stateless:  true
            switch_user: { role: ROLE_SUPER_ADMIN, parameter: _want_to_be_this_user }
            logout: { path: /admin/logout, target: / }

AdminBundle /资源/配置/ routing.yml中

logout:
    pattern:   /logout

应用/配置/ routing.yml中

admin:
    resource: "@AdminBundle/Resources/config/routing.yml"
    prefix:   /admin

授权仍然存在,因为标头状态Authorization:Basic YWRtaW46cEAkJHcwUmQh所以我想在请求期间仍然会向应用程序提供凭据。

我知道根据this question没有正确的方式从HTTP Basic Auth退出,但Symfony2可以允许吗?

2 个答案:

答案 0 :(得分:11)

通过http auth登录后,您的浏览器将缓存并以标题形式将您的登录凭据添加到每个后续请求中,如下所示:

Authorization:Basic YWRtaW46YWRtaW4=

当您进行注销时,对服务器的下一个请求仍将保留您的http凭据并再次登录。

因此诀窍是在服务器端销毁会话后丢失客户端的http凭据。

在过去那里有一些hackidy方法,如提交虚假凭据或一些模糊的IE方法来删除缓存。但我不认为这些方法仍然有效。

什么仍然有效(我使用symfony 2.7和谷歌浏览器45测试了以下方法)正在使用HTTP 401未经授权的响应回复客户端。

检查出来:

将以下内容添加到app / config / security.yml文件

中的注销部分
logout:
    success_handler: logout_listener

到您的服务配置app / config / services.yml

logout_listener:
    class: AppBundle\LogoutListener

然后创建一个响应HTTP 401未授权的侦听器

<?php 

namespace AppBundle;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface;

class LogoutListener implements  LogoutSuccessHandlerInterface 
{
    public function onLogoutSuccess(Request $request) 
    {
        return new Response('', 401);
    }
}

注销后,您的应用会向浏览器发送401,认为身份验证失败导致身份验证缓存被清除(无论如何,谁想要记住错误的凭据)并再次提示您的凭据

答案 1 :(得分:0)

@Niki Van Cleemput的回答似乎并不适用于所有情况。当我测试它时,它在Chrome 44上是可以的,但在Firefox 48上没有。 这是一个受HTTP authentication logout via PHP启发的解决方案:

安全参数:

security:
    # ... your encoders, role_hierarchy, providers...
    firewalls:
        dev:
            pattern:  ^/(_(profiler|wdt)|css|images|js)/
            security: false

        main:
            pattern: ^/
            anonymous: ~
            stateless:  true
            http_basic:
                realm: "My admin area"
            # no logout parameter as it is handled manually

    access_control:
        - { path: ^/admin, roles: ROLE_ADMIN }

带有&#34;假冒&#34;的控制器注销行动:

<?php

namespace Me\Bundle\CoreBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

/**
 * Security stuff.
 */
class SecurityController extends Controller
{
    /**
     * Logout confirmation.
     *
     * @Route("/logout", name="logout")
     */
    public function logoutAction()
    {
        return $this->render('@EasyAdmin/default/logout.html.twig'); // change with your template path
    }
}

在你的布局中:

<script type="text/javascript">
    function logout() {
        var xmlhttp;
        if (window.XMLHttpRequest) {
            xmlhttp = new XMLHttpRequest();
        }
        // code for IE
        else if (window.ActiveXObject) {
            xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
        }
        if (window.ActiveXObject) {
            // IE clear HTTP Authentication
            document.execCommand("ClearAuthenticationCache");
            window.location.href='{{ path('logout') }}';
        } else {
            xmlhttp.open("GET", '{{ path('easyadmin') }}', true, "logout", "logout");
            xmlhttp.send("");
            xmlhttp.onreadystatechange = function() {
                if (xmlhttp.readyState == 4) {window.location.href='{{ path('logout') }}';}
            }
        }

        return false;
    }
</script>

添加注销链接:

<a href="#" onclick="logout()"><i class="hidden-xs fa fa-user"></i> Logout</a>

至少它适用于Chrome和Firefox,如果它不在其他浏览器上,请告诉我。