我正在为我的REST API使用FosrestBundle,到目前为止,它一直是一个很棒的工具。我使用HTTP Basic Auth,在大多数情况下,它的工作正常。但是,当提交不良的凭据时,我对捆绑包的例外行为有问题。处理异常(通过集成身份验证处理程序或异常映射配置)时,该捆绑包总是为我提供与正确的HTTP状态和JSON/XML内容相似的响应:

{
   "code": 401,
   "message": "You are not authenticated"
}

这很好,当 没有身份验证 信息完全提交。但是,提交 不好的信用史 (例如,未知的用户名或不正确的密码)我将获得HTTP代码401不良凭据(很好)带有空白的消息主体。相反,我本来会期望与上面的JSON相似。

这是我身边的错误还是配置问题? 我也很想知道这些类型的身份验证错误是如何完全由捆绑包处理的,因为 BadCredentialsExceptioncodes 捆绑包的异常配置部分的部分似乎被忽略了。

谢谢!

有帮助吗?

解决方案

好吧,在挖掘捆绑包的代码后,我弄清楚了。问题是由Symfony的HTTP基本身份验证影响来处理不良凭证的方式。这 401 Bad Credentials 响应是由自定义响应创建的 BasicAuthenticationEntryPoint, ,这是由 BasicAuthenticationListener' handle 功能,立即在 AuthenticationException 已抛出相同的功能。因此,听众无法与听众一起捕捉这个例外:

public function handle(GetResponseEvent $event)
{
    $request = $event->getRequest();

    if (false === $username = $request->headers->get('PHP_AUTH_USER', false)) {
        return;
    }

    if (null !== $token = $this->securityContext->getToken()) {
        if ($token instanceof UsernamePasswordToken && $token->isAuthenticated() && $token->getUsername() === $username) {
            return;
        }
    }

    if (null !== $this->logger) {
        $this->logger->info(sprintf('Basic Authentication Authorization header found for user "%s"', $username));
    }

    try {
        $token = $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $request->headers->get('PHP_AUTH_PW'), $this->providerKey));
        $this->securityContext->setToken($token);
    } catch (AuthenticationException $failed) {
        $this->securityContext->setToken(null);

        if (null !== $this->logger) {
            $this->logger->info(sprintf('Authentication request failed for user "%s": %s', $username, $failed->getMessage()));
        }

        if ($this->ignoreFailure) {
            return;
        }

        $event->setResponse($this->authenticationEntryPoint->start($request, $failed));
    }
}

入口点的 start 函数创建自定义响应,但涉及不例外:

public function start(Request $request, AuthenticationException $authException = null)
{
    $response = new Response();
    $response->headers->set('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realmName));
    $response->setStatusCode(401, $authException ? $authException->getMessage() : null);

    return $response;
}

拳头 if- 在 handle 上面的函数还解释了为什么在“根本没有用户凭据”的情况下起作用,因为在这种情况下,听众只是停止尝试对用户进行身份验证,因此Symfony的防火墙听众会抛出一个例外(不确定在哪里确实),所以Fosrestbundle AccessDeniedListener 能够抓住 AuthenticationException 并做事。

其他提示

您可以扩展 AccessDeniedListener 并告诉fosrestbundle使用您自己的侦听器与参数 %fos_rest.access_denied_listener.class%. (服务定义)

parameters:
    fos_rest.access_denied_listener.class: Your\Namespace\For\AccessDeniedListener

然后添加额外的检查 BadCredentialsException 并将 HttpException 带有所需的代码/消息,类似 第70行.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top