当某处被抛出时,我想消除重定向的不良影响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());
}
}
新问题是 - 它会导致任何安全问题吗? 我认为这是一个好方法。