さて、バンドルのコードをもう少し掘り下げた後、私はそれを理解しました。この問題は、SymfonyのHTTP基本認証の印象によって、悪い資格情報が処理される方法から生じます。 401 Bad Credentials
応答は、によって作成されたカスタム応答です BasicAuthenticationEntryPoint
, 、それによって呼ばれます BasicAuthenticationListener
's 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
- clause handle
上記の関数は、「ユーザー資格情報がまったくない」場合に機能する理由も説明しています。その場合、リスナーはユーザーの認証を停止するだけであるため、Symfonyのファイアウォールリスナーによって例外がスローされます(どこにあるのかわかりません正確に)、fosrestbundle's AccessDeniedListener
キャッチすることができます AuthenticationException
そしてそのことをします。