如何从安全组件覆盖一个类?

时间:2015-02-02 13:05:22

标签: php symfony authentication silex

我在我的API(Silex)中使用Basic Auth,端点从客户端接收用户+ pw,通过基本身份验证验证用户,然后返回用于进一步请求的令牌。现在当我的应用程序进行AJAX调用时,如果凭据是正确的,那么一切都顺利进行。如果凭据错误,API将返回401和设置的WWW-Authenticate标头。这会导致浏览器自动显示默认的浏览器登录表单。

我不希望这种情况发生。在StackOverflow中,他们说只有两个解决方案要么返回400而不是401,要么将WWW-Authenticate标题更改为'FormBased'。

在安全组件的BasicAuthenticationEntryPoint.php中,statusCode设置为401,WWW-Authenticate设置为“Basic ...”。

如果我在那里应用更改,它可以工作......但我需要将其作为我的项目的一部分...我应该如何覆盖Symfony \ Component \ Security \ Http \ EntryPoint \ BasicAuthenticationEntryPoint.php以使其适应根据我的需要?任何想法是否有解决方法?我明白这应该是一个非常普遍的问题,它是如何解决的?

1 个答案:

答案 0 :(得分:0)

好的,所以这就是我做过的事,万一有人想知道:

首先在我的Security文件夹中,我创建了自己的BasicAuthenticationEntryPoint.php版本

<?php

/*
 * Redefinition of the Symfony's BasicAuthenticationEntryPoint
 */

namespace multikanban\multikanban\Security\Http\EntryPoint;

use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;

/**
 * BasicAuthenticationEntryPoint starts an HTTP Basic authentication.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class BasicAuthenticationEntryPoint implements AuthenticationEntryPointInterface
{
    private $realmName;

    public function __construct($realmName)
    {
        $this->realmName = $realmName;
    }

    /**
     * {@inheritdoc}
     */
    public function start(Request $request, AuthenticationException $authException = null)
    {
        $response = new Response();
        $response->headers->set('WWW-Authenticate', 'FormBased');
        $response->setStatusCode(401);

        return $response;
    }
}

请注意,我做了两件事:

  1. 添加AuthenticationEntryPointInterface的使用。
  2. 将WWW-Authenticate值更改为“FormBased”,这是对原始文件的实际修改,以便当服务器返回401 Unauthorized时,浏览器不显示默认提示。 (你也可以返回400但你真的不会遵守标准)
  3. 其次,我在我的Silex应用程序中定义了这样的服务:

        $this['security.entry_point.main.http'] = $this->share(function() {
            return new BasicAuthenticationEntryPoint('main');
        });
    

    'main'是我的防火墙名称。

    显然,我还在Application.php的顶部添加了用法:

    use multikanban\multikanban\Security\Http\EntryPoint\BasicAuthenticationEntryPoint;