どこかがスローされたときのリダイレクトの望ましくない影響を取り除きたい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());
}
}
新しい質問は - セキュリティ上の問題を引き起こす可能性がありますか? これはいい方法だと思います。