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 !