質問

私はREST APIにFosrestBundleを使用していますが、これまでのところ素晴らしいツールでした。私はHTTP Basic Authを使用しており、ほとんどの場合、それは正常に機能します。ただし、悪い資格情報が提出された場合、バンドルの例外動作に問題があります。例外を処理する場合(統合認証ハンドラーまたは例外マッピング構成を介して)、バンドルは常に正しいHTTPステータスとこれに類似したJSON/XMLコンテンツで応答を提供します。

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

これは問題ありません、いつでも動作します 認証なし 情報はまったく提出されます。ただし、提出するとき 悪い資格情報 (例:不明なユーザー名または誤ったパスワード)空のメッセージ本文を使用してHTTPコード401悪い資格情報(問題ありません)を取得します。代わりに、私は上記のJSONに似た何かを期待していたでしょう。

それは私の側のバグですか、それとも構成の問題ですか? また、これらの種類の認証エラーがバンドルによって正確に処理される方法を知りたいです。 BadCredentialsExceptionのステータスコード codes Bundleの例外構成セクションのセクションは無視されているようです。

ありがとう!

役に立ちましたか?

解決

さて、バンドルのコードをもう少し掘り下げた後、私はそれを理解しました。この問題は、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 そしてそのことをします。

他のヒント

拡張できます AccessDeniedListener そして、fosrestbundleにパラメーターを使用して自分のリスナーを使用するように伝えます %fos_rest.access_denied_listener.class%. (サービス定義)

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

次に、追加のチェックを追加します BadCredentialsException そしてemmit an HttpException 認証エクセプトのチェックと同様の目的のコード/メッセージを使用して 70行目.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top