Va bene, dopo aver scavato un po 'di più nel codice del pacchetto, l'ho capito. Il problema deriva dal modo in cui le credenziali cattive vengono gestite dall'impegnazione di autenticazione di base HTTP di Symfony. Il 401 Bad Credentials
La risposta è una risposta personalizzata creata da BasicAuthenticationEntryPoint
, che è chiamato dal BasicAuthenticationListener
'S handle
funzione, immediatamente dopo un AuthenticationException
è stato lanciato nella stessa funzione. Quindi non c'è modo di catturare questa eccezione con un ascoltatore:
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));
}
}
I punti di ingresso start
La funzione crea la risposta personalizzata, senza eccezioni coinvolte:
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;
}
Il pugno if
-Clause nel handle
La funzione sopra spiega anche perché funziona nel caso di "nessuna credenziale dell'utente", dal momento che in quel caso, l'ascoltatore smette solo di provare ad autenticare l'utente, e quindi un'eccezione verrà lanciata dagli ascoltatori di firewall di Symfony (non è sicuro esattamente), quindi di FosrestBundle AccessDeniedListener
è in grado di catturare il AuthenticationException
E fai le sue cose.