首页 > 解决方案 > 重写前日志中的 AccessDeniedException

问题描述

在 4.1 中,当用户想要在具有安全性的页面中访问时(例如 @Security("has_role('ROLE_ADMIN')" ),用户将在登录页面中被重定向。它正在工作。我没有错误 500。

但是在我的日志 /var/log/prod.log 中我有一些错误:

[2018-06-06 09:30:47] request.CRITICAL: Uncaught PHP Exception Symfony\Component\Security\Core\Exception\AccessDeniedException: "Access Denied." at /var/www/website/vendor/symfony/security/Http/Firewall/AccessListener.php line 68 {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException(code: 403): Access Denied. at /var/www/website/vendor/symfony/security/Http/Firewall/AccessListener.php:68)"} []
[2018-06-06 09:30:47] security.DEBUG: Access denied, the user is not fully authenticated; redirecting to authentication entry point. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AccessDeniedException(code: 403): Access Denied. at /var/www/website/vendor/symfony/security/Http/Firewall/AccessListener.php:68)"} []
[2018-06-06 09:30:47] security.DEBUG: Calling Authentication entry point. [] []

我不明白为什么我有严重错误。

标签: symfonysymfony4

解决方案


Symfony 框架定义了一个以2048的非常高优先级Symfony\Component\HttpKernel\EventListener\ExceptionListener订阅的方法(参见https://github.com/symfony/http-kernel/blob/master/EventListener/ExceptionListener.php#L93):KernelEvents::EXCEPTIONlogKernelException

public static function getSubscribedEvents()
{
    return array(
        KernelEvents::EXCEPTION => array(
            array('logKernelException', 2048),
            array('onKernelException', -128),
        ),
    );
}

所以抛出AccessDeniedException首先由这种方法处理,该方法以CRITICALlogKernelException级别记录它(参见https://github.com/symfony/http-kernel/blob/master/EventListener/ExceptionListener.php#L109):

protected function logException(\Exception $exception, $message)
{
    if (null !== $this->logger) {
        if (!$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500) {
            $this->logger->critical($message, array('exception' => $exception));
        } else {
            $this->logger->error($message, array('exception' => $exception));
        }
    }
}

到这一步,AccessDeniedException已经登录到请求频道了。它与请求范围完全相关:原始请求失败,因为没有执行身份验证......

然后,Symfony\Component\Security\Http\Firewall\ExceptionListener监听KernelEvents::EXCEPTION但仅处理与身份验证相关的那些(请参阅https://github.com/symfony/security/blob/master/Http/Firewall/ExceptionListener.php#L87)继续执行任务以重定向到身份验证起点。 ..


推荐阅读