如何从 Symfony 5 中的 EventSubscriber 重定向

How to redirect from a EventSubscriber in Symfony 5

我正在尝试为 Symfony5 编写自定义身份验证检查器。这是针对选定控制器的 运行,所有控制器都有一个 AuthenticationControllerInterface,其中包括许多其他相关代码位。

我正在尝试使用绑定到 ControllerEvent 的 EventSubscriber。这将检查此接口并正确识别相关控制器。

上下文请看下面:


class BearerTokenSubscriber implements EventSubscriberInterface
{

    public function onKernelController(ControllerEvent $event)
    {
            $controller = $event->getController();

            // load the controller
            if (is_array($controller)) {
                $controller = $controller[0];
                if ($controller instanceof AuthenticationControllerInterface) {
                    if(
                       // my assorted auth functionality: works as expected
                    ) {
                        //... where my question lies:
                    }
                }
            }
        }
    }

    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::CONTROLLER => 'onKernelController',
        ];
    }
}

在“我的问题所在”:是我想做重定向的点...通过以下方式(按优先顺序):

  1. 返回特定的控制器方法(我有一个 403 预配置)。
  2. 重定向到另一个 URL(带有 403)

提前致谢。

您可以使用 ControllerEvent::setController($myController) 在满足您的条件后提供您选择的控制器:

class TestControllerEventSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        $events = [];
        $events[KernelEvents::CONTROLLER] = ['onKernelController', 0];
        return $events;
    }

    public function onKernelController(ControllerEvent $event): void
    {
        $controller = $this->getControllerObjectFromEvent($event);
        // Check if your conditions are met
        if ($controller instanceof AuthenticationControllerInterface && $whateverElse) {
            $event->stopPropagation();
            // Set your custom controller that produces a 403 response
            $event->setController(static function () {
                return new Response(null, 403);
            });
        }
    }

    private function getControllerObjectFromEvent(ControllerEvent $event): ?object
    {
        $controller = $event->getController();
        if (true === is_object($controller)) {
            return (object) $controller;
        }
        if (false === is_array($controller)) {
            return null;
        }
        foreach ($controller as $value) {
            if (true === is_object($value)) {
                return $value;
            }
        }
        return null;
    }
}

我的具体答案是:


if (/* some test logic */) {
    $event->stopPropagation();
    $event->setController(
        static function () use ($controller) {
            return $controller->some403ErrorResponse();
        }
    );
}

非常感谢 Jeroen 为我指明了正确的方向。 也已将他的标记为正确。