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

Publié le 24 avril 2016
#symfony

Par défaut, l'utilisateur est redirigé vers la dernière page visitée ou la page par défaut spécifiée. Mais comment diriger nos utilisateurs différemment 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 implements AuthenticationSuccessHandlerInterface
{
    private $router;

    public function __construct(RouterInterface $router)
    {
        $this->router = $router;
    }

    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(Request $request, TokenInterface $token) 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 a 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 !

gkueny

À propos de l'auteur - gkueny @ZETurf

Développeur depuis maintenant 8 ans et à mon compte depuis 3 ans, j'ai une grande affinité avec le front-end et les tests bien fait. Pas full-stack mais touche à tout, je suis également à l'aise sur le développement mobile avec react-native et le développement backend Symfony / php.