Question

J'utilise FosRestBundle pour mon API REST et jusqu'à présent, cela a été un excellent outil. J'utilise HTTP Basic Auth et dans la plupart des cas, cela fonctionne très bien. Cependant, j'ai des problèmes avec le comportement d'exception du bundle lorsque de mauvaises informations d'identification sont soumises. Lors de la gestion des exceptions (via les gestionnaires d'authentification intégrés ou la configuration de mappage des exceptions), le bundle me donne toujours une réponse avec l'état HTTP correct et le contenu JSON / XML similaire à ceci:

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

C'est bien, ça marche aussi quand pas d'authentification Les informations sont soumises du tout. Cependant, lors de la soumission Mauvaises qualifications (par exemple, nom d'utilisateur inconnu ou mot de passe incorrect) J'obtiens le code HTTP 401 Bad Indementiels (ce qui est bien) avec un corps de message vide. Au lieu de cela, je m'attendais à quelque chose de similaire au JSON ci-dessus.

Est-ce un bug ou un problème de configuration de mon côté? J'aimerais aussi savoir comment ces types d'erreurs d'authentification sont exactement gérés par le bundle, car il subminisant le BadCredentialsExceptionCode d'état dans le codes La section de la section de configuration des exceptions du bundle semble être ignorée.

Merci!

Était-ce utile?

La solution

D'accord, après avoir creusé un peu plus dans le code du bundle, je l'ai compris. Le problème résulte de la façon dont les mauvaises informations d'identification sont gérées par la souci d'authentification de base HTTP de Symfony. La 401 Bad Credentials La réponse est une réponse personnalisée créée par BasicAuthenticationEntryPoint, qui est appelé par le BasicAuthenticationListener's handle fonction, immédiatement après un AuthenticationException a été lancé dans la même fonction. Il n'y a donc aucun moyen d'attraper cette exception avec un auditeur:

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));
    }
}

Le point d'entrée start La fonction crée la réponse personnalisée, sans exceptions impliquées:

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;
}

Le poing if-crave dans le handle La fonction ci-dessus explique également pourquoi cela fonctionne dans le cas de "aucune information d'identification du tout", car dans ce cas, l'auditeur cesse d'essayer d'authentifier l'utilisateur, et donc une exception sera lancée par les auditeurs de pare-feu de Symfony (je ne sais pas trop où Exactement), donc Fosrestbundle AccessDeniedListener est capable d'attraper le AuthenticationException Et faites son truc.

Autres conseils

Vous pouvez étendre AccessDenedListener et dire à Fosrestbundle d'utiliser votre propre auditeur avec le paramètre %fos_rest.access_denied_listener.class%. (Définition du service)

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

Puis ajoutez un chèque supplémentaire pour BadCredentialsException et emmit an HttpException avec le code / message souhaité similaire au chèque pour AuthenticationException à Ligne 70.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top