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,则在将安全区域添加到防火墙映射时提供的异常侦听器将跳入。

异常侦听器根据创建时收到的参数确定接下来会发生什么。它可能会启动身份验证过程,可能会要求用户再次提供他们的凭据(当他们仅基于“记住我”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 调试器在 auth 之后显示 2 个异常。(正如它应该):

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

第一AccessDeniedException和第二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