Home > Symfony tips : Rediriger après le login selon le ROLE de l'utilisateur

Symfony tips : Rediriger après le login selon le ROLE de l'utilisateur

Par défaut, l’utilisateur est redirigé vers la dernière page visité ou la page par défaut spécifié. Mais comment diriger nos utilisateurs différamment selon leur ROLE ?

Posons le problème :

  • Je veux que l’administrateur soit redirigé vers la page admin
  • Je veux que l’utilisateur lambda soit redirigé vers la page home

Comment faire ?

Par défaut, l’utilisateur est redirigé vers la dernière page qu’il a visitée. On peut modifier cette redirection par défaut en rajoutant default_target_path: /ma-page dans notre fichier security.yml :

firewalls:
    main:
        pattern: ^/
        form_login:
            provider: fos_userbundle
            login_path: /
            default_target_path: /page
            csrf_token_generator: security.csrf.token_manager
        logout: true
        anonymous: true
(J’utilise ici le bundle FOSUserBundle)

Mais nous sommes toujours confrontés à notre problème. Tout le monde sera redirigé vers cette page.

Solution

Pour régler notre problème nous allons créer un service qui aura pour charge de rediriger l’utilisateur selon son rôle, puis nous l’appellerons au bon moment.

Créons tout d’abord notre service :

<?php

namespace AppBundle\Listener;

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;

/**
 * Class AfterLoginRedirection
 *
 * @package AppBundle\AppListener
 */
class AfterLoginRedirection implements AuthenticationSuccessHandlerInterface
{
    private $router;

    /**
     * AfterLoginRedirection constructor.
     *
     * @param RouterInterface $router
     */
    public function __construct(RouterInterface $router)
    {
        $this->router = $router;
    }

    /**
     * @param Request        $request
     *
     * @param TokenInterface $token
     *
     * @return RedirectResponse
     */
    public function onAuthenticationSuccess(Request $request, TokenInterface $token)
    {
        $roles = $token->getRoles();

        $rolesTab = array_map(function ($role) {
            return $role->getRole();
        }, $roles);

        if (in_array('ROLE_ADMIN', $rolesTab, true)) {
            // c'est un aministrateur : on le rediriger vers l'espace admin
            $redirection = new RedirectResponse($this->router->generate('amin'));
        } else {
            // c'est un utilisaeur lambda : on le rediriger vers l'accueil
            $redirection = new RedirectResponse($this->router->generate('homepage'));
        }

        return $redirection;
    }
}

Nous implémentons l’interface AuthenticationSuccessHandlerInterface qui nous fournit la fonction onAuthenticationSuccess qui nous intéresse. Vous pouvez maintenant mettre votre propre logique.

On n’oublie pas d’enregistrer notre service :

services:
    redirect.after.login:
        class: AppBundle\Listener\AfterLoginRedirection
        arguments: ['@router']

Et enfin nous informons le firewall qu’il faut appeler ce service lorsque l’utilisateur à réussi à s’authentifier :

firewalls:
    main:
        pattern: ^/
        form_login:
            provider: fos_userbundle
            login_path: /
            csrf_token_generator: security.csrf.token_manager
            success_handler: redirect.after.login
        logout: true
        anonymous: true

Et voila !