检查 header 特定控制器

check header for a specific controller

我需要检查在访问 BooksController 时是否收到 header 'X-API-User-Name = admin'。

我用这个文档https://symfony.com/doc/current/event_dispatcher/before_after_filters.html

代码 这是我的中间件

namespace App\Event;

use App\Controller\BooksController;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\ResponseEvent;

class HeaderChecker implements EventSubscriberInterface
{
    const HEADER = 'X-API-User-Name';

    public function onKernelController(ControllerEvent $event): void
    {
        $controller = $event->getController();
        if (is_array($controller)) {
            $controller = $controller[0];
        }

        if ($controller instanceof BooksController) {
            $header = $event->getRequest()->headers->has(self::HEADER);
            if (!$header) return new JsonResponse(['message' => 'Header X-API-User-Name is not found'], Response::HTTP_FORBIDDEN);

            $admin = $event->getRequest()->headers->get(self::HEADER);
            if ($admin !== 'admin') return new JsonResponse(['message' => 'Header X-API-User-Name is not valid'], Response::HTTP_FORBIDDEN);
        }
    }

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

service.yaml代码

App\Event\HeaderChecker:
        tags:
            - { name: kernel.event_subscriber, event: kernel.exception, method: 'onKernelController' }

问题: 通过 var_dump 我检查了数据是否正在输入,但事情是这样的。如果 X-API-User-Name 不是管理员,我需要发送状态为 403 的 JsonResponse。但是如果 X-API-User-Name 不是管理员,我的 EventSubscriber class 不会 return JsonResponse。我的错误是什么?

这里发生了几件事。如果您使用的是 EventSubscriber,那么 services.yaml 中不需要任何额外的行。从评论中我认为你已经明白了。

要验证您的监听器是否正确连接,请使用 bin/console debug:event-dispatcher kernel.controller。你的听众应该出现。您也可以简单地添加一个转储语句。

清除后,请注意您的 onKernelController 方法有一个 return 类型的 void。你可以 return 任何你想要的,但这不会有什么不同。您 return 的任何内容都将被忽略。这实际上带来了所有这些如何实施的问题?在我看来,查看 HttpKernel::handleRaw 方法非常有启发性。乍一看有点让人不知所措,但它确实显示了内核事件何时触发以及之后发生的事情。

回到如何指示需要 json 响应的问题,RequestEvent 等事件有一个 setResponse 方法。唉,你不知道有请求事件的控制器。

遗憾的是,ControllerEvent 没有 setResponse 方法。相反,它有一个 setController 方法,这意味着您实际上可以更改控制器。

因此您需要执行一个控制器操作,return 是您的 json 响应。然后你使用 $kernel->setController($controller) 来使用它。由于文档中有示例,因此我不会显示详细代码。

有点牵强。可能更容易只检查控制器操作本身中的 headers 并完成它。另一方面,一旦你让它工作并理解它为什么工作,那么你就有了一个对未来非常有用的工具。

最后一个想法:如果这是关于访问控制的,那么你应该抛出一个访问被拒绝的异常。给黑客内部安全信息毫无意义。是否真的存在合法用户无需 header 即可访问此控制器的情况?