I need to check that when accessing the BooksController, the header 'X-API-User-Name = admin' is received.
I use this documetations https://symfony.com/doc/current/event_dispatcher/before_after_filters.html
Code It's my middleware
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 code
App\Event\HeaderChecker:
tags:
- { name: kernel.event_subscriber, event: kernel.exception, method: 'onKernelController' }
Problem: Through var_dump I checked that the data is coming in, but here's the thing. I need to send a JsonResponse with a 403 status if the X-API-User-Name is not admin. But my EventSubscriber class does not return JsonResponse if X-API-User-Name is not admin. What's my mistake?
CodePudding user response:
Try use this helper header()
, this must retorn all keys of your header, to get the X-API-User-Name use, header('X-API-User-Name)
, a other way is use request()
and access through him.
CodePudding user response:
Couple of things going on here. If you are using an EventSubscriber then there is no need for any additional lines in services.yaml. From the comments I think you have figured this out.
To verify your listener is wired properly, use bin/console debug:event-dispatcher kernel.controller
. Your listener should show up. You could also simply add a dump statement.
With that cleared up, notice that your onKernelController method has a return type of void. You can return anything you want but it won't make a difference. Anything you return is ignored. Which actually brings the question of how is all this implemented anyways? It is very instructive, in my opinion, to look at the HttpKernel::handleRaw method. It's bit overwhelming at first glance but it does show when the kernel events are fired and what happens afterward.
Returning to the issue of how one does indicate a json response is needed, events such as the RequestEvent have a setResponse method. Alas you don't know the controller with a request event.
Sadly, the ControllerEvent does not a setResponse method. Instead it has a setController method which means that you can actually change the controller.
So you need to make a controller action that returns your json response. And then you use $kernel->setController($controller) to use it. I won't show the detailed code as the documentation has examples.
It is a bit involved. Might be easier to just check the headers in the controller action itself and be done with it. On the other hand, once you get it working and understand why it works then you have a very useful tool for the future.
One final thought: if this is about access control then you should probably just throw an access denied exception. No point in given a hacker internal security information. Are there really cases where a legitimate user should be able access this controller without the header?