Muy bien, después de profundizar en el código del paquete un poco más, lo descubrí. El problema resulta de la forma en que las credenciales malas se manejan por la impementación de autenticación básica HTTP de Symfony. los 401 Bad Credentials
La respuesta es una respuesta personalizada creada por BasicAuthenticationEntryPoint
, que es llamado por el BasicAuthenticationListener
's handle
función, inmediatamente después de un AuthenticationException
ha sido arrojado en la misma función. Por lo tanto, no hay forma de atrapar esta excepción con un oyente:
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));
}
}
El punto de entrada start
La función crea la respuesta personalizada, sin excepciones involucradas:
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;
}
El puño if
-Lausar en el handle
La función anterior también explica por qué funciona en el caso de "no hay credenciales de usuario", ya que en ese caso, el oyente simplemente deja de intentar autenticar al usuario y, por lo tanto, la excepción será lanzada por los oyentes de firewall de Symfony (no estoy seguro de dónde exactamente), así que fosrestbundle's AccessDeniedListener
es capaz de atrapar el AuthenticationException
y hacer lo suyo.