Search code examples
phpsymfonysymfony5

Redirect from event subscriber


I want to redirect user conditionally from my event subscriber on kernel.controller event and change it if user can't access the one asked.

<?php

namespace App\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\RouterInterface;

class WebPageAccessSuscriber implements EventSubscriberInterface
{
    /**
     * @var SessionInterface
     */
    private $session;

    /**
     * Contient l'ensemble des parametres de config
     *
     * @var ParameterBagInterface
     */
    private $params;

    private $router;

    public function __construct(SessionInterface $session, ParameterBagInterface $params, RouterInterface $router)
    {
        // Retrieve the client session
        $this->session = $session;

        // Retrieve configuration variable
        $this->params = $params;

        $this->router = $router;
    }

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

        if(!is_array($controller)) return;

        if ($this->params->get('visitor_access') === false && $controller[0] instanceof \App\Controller\restictedController) {

            $event->setController(function() use ($event) {
                return new RedirectResponse($this->router->generate('login_' . $event->getRequest()->getLocale()));
            });
        }
    }

    public static function getSubscribedEvents()
    {
        return [
            // must be registered before (i.e. with a higher priority than) the default Locale listener
            KernelEvents::CONTROLLER => [['onKernelController']]
        ];
    }
}

It works but symfony web profiler doesn't shows anymore.

I mean it does but his content is the one from my login template

enter image description here

Why symfony is redirecting webprofiler to login page ? How can prevent this behavior ? Should I use another way to achieve this ?


Solution

  • If you want to protect a whole section of your application use the symfony security component to create a firewall with its own authentication.

    If you want to protect specific pages you could use a Security Voter https://symfony.com/doc/current/security/voters.html

    Edit: After denying access via a Voter you can redirect the user with a https://symfony.com/doc/current/security/access_denied_handler.html