2

どこかがスローされたときのリダイレクトの望ましくない影響を取り除きたいAccesDeniedExceptionです。ユーザーが認証されていない場合、「ログイン」ページにリダイレクトすることを意味します。

kernel.exceptionリスナーを作成しました

class ApiAccessDeniedListener implements EventSubscriberInterface
{
    private $format;

    public function __construct($format = 'json')
    {
        $this->format = $format;
    }

    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        $exception = $event->getException();
        // here some conditions
        if($exception instanceof AccessDeniedException){
            $exception = new AccessDeniedHttpException('You do not have the necessary permissions', $exception);
        }
    }

    public static function getSubscribedEvents()
    {
        return array(
            KernelEvents::EXCEPTION => array('onKernelException', 5),
        );
    }
}

このリスナーは正しい順序で正しく機能しますが、常にファイアウォールによってログイン ページにリダイレクトされます。 symfony のドキュメントには次のように書かれています。

例外リスナー

いずれかのリスナーが AuthenticationException をスローすると、ファイアウォール マップに保護された領域を追加するときに提供された例外リスナーが飛び込みます。

例外リスナーは、作成時に受け取った引数に基づいて、次に何が起こるかを決定します。認証手順を開始したり、("remember-me" Cookie に基づいてのみ認証された場合に) ユーザーに資格情報を再度提供するように求めたり、例外を AccessDeniedHttpExceptionに変換したりして、最終的に "HTTP /1.1 403: アクセスが拒否されました」という応答。

わかりました - スローAccessDeniedHttpExceptionすると、リダイレクトではなくインスタント 403 が返されます。正しいですか?

第二に、symfony とExceptionListenerには同じトリックがあることを掘り下げましたか? おもう...

private function handleAccessDeniedException(GetResponseForExceptionEvent $event, AccessDeniedException $exception)
{
    $event->setException(new AccessDeniedHttpException($exception->getMessage(), $exception));
    //...
}

さらに、symfony デバッガーは認証後に 2 つの例外を表示します。(そうあるべきです):

Unable to access this page!
403 Forbidden - AccessDeniedHttpException
1 linked Exception: ... (and here AccessDeniedException)

最初AccessDeniedExceptionと 2 番目AccessDeniedHttpException

どうすれば問題を解決できますか? インスタント 403 エラーをスローするにはどうすればよいですか?


編集

どこに問題があるのか​​ わかりました。ファイアウォールExceptionListenerは、以前のすべての例外をループでチェックします。

    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        $exception = $event->getException();
        do {
            if ($exception instanceof AuthenticationException) {
                return $this->handleAuthenticationException($event, $exception);
            } elseif ($exception instanceof AccessDeniedException) {
                return $this->handleAccessDeniedException($event, $exception);
            } elseif ($exception instanceof LogoutException) {
                return $this->handleLogoutException($exception);
            }
        } while (null !== $exception = $exception->getPrevious());
    }

リスナーを次のように変更できます。

public function onKernelException(GetResponseForExceptionEvent $event)
{
    $exception = $event->getException();
    // here some conditions
    if($exception instanceof AccessDeniedException){
        //old version
        //$exception = new AccessDeniedHttpException('You do not have the necessary permissions', $exception);
        $exception = new AccessDeniedHttpException('You do not have the necessary permissions', $exception->getPrevious());
    }
}

新しい質問は - セキュリティ上の問題を引き起こす可能性がありますか? これはいい方法だと思います。

4

0 に答える 0