44 votes

Symfony2 : comment déconnecter manuellement un utilisateur dans un contrôleur ?

Je voudrais faire quelque chose comme ça dans le contrôleur pour déconnecter l'utilisateur :

$user = $this->get('security.context')->getToken()->getUser();
$user->logOut();

79voto

Crozin Points 22346

La déconnexion dans Symfony2 est gérée par ce que l'on appelle le gestionnaire de déconnexion qui est juste une liste qui est exécutée lorsque l'URL correspond à un modèle de la configuration de sécurité, c'est-à-dire que si l'URL est, disons /logout alors ce listener est exécuté. Il existe deux gestionnaires de déconnexion intégrés :

  1. CookieClearingLogoutHandler qui efface simplement tous les cookies.
  2. SessionLogoutHandler ce qui invalide la session

Tout ce que vous avez à faire, c'est la même chose que le dernier. Vous pouvez le faire en appelant simplement :

Legacy Symfony

$this->get('security.context')->setToken(null);
$this->get('request')->getSession()->invalidate();

Symfony 2.6

$this->get('security.token_storage')->setToken(null);
$this->get('request')->getSession()->invalidate();

Avertissement

Cela ne fonctionnera que si se souvenir de moi est désactivée. Dans le cas contraire, l'utilisateur sera à nouveau connecté au moyen d'un cookie "remember me" lors de la prochaine demande.

Veuillez envisager la solution étendue si vous utilisez la fonctionnalité "Se souvenir de moi" : https://stackoverflow.com/a/28828377/1056679

14 votes

Vous devez également définir le jeton de sécurité à null : $this->get('security.context')->setToken(null); $this->get('request')->getSession()->invalidate();

5 votes

Il doit y avoir un événement qui peut être déclenché, je ne peux pas croire qu'ils nous ont laissé sans un moyen fiable qui préserve les paramètres locaux et déconnecte l'utilisateur.

4 votes

NOTE : Obtenir l'objet Request de cette manière est obsolète depuis la version 2.4. Injectez la requête dans le contrôleur ou la pile de requêtes de l'utilisateur : symfony.com/blog/new-in-symfony-2-4-the-request-stack

10voto

Francis Alvin Points 141

L'invalidation de la session de l'utilisateur peut entraîner des résultats indésirables. Le pare-feu de Symfony a un auditeur qui vérifie et rafraîchit toujours le jeton de l'utilisateur. Vous pourriez simplement faire une redirection vers la route de déconnexion par défaut que vous avez spécifiée dans votre fichier firewall.yml (ou security.yaml )

Dans le contrôleur, vous pouvez le faire :

$this->redirect($this->generateUrl('your_logout_url'));

Si vous ne connaissez pas le nom de la route de déconnexion ( your_logout_url ), vous pouvez l'obtenir depuis la console Symfony en utilisant cette commande :

app/console router:match /logout

Ou des versions plus récentes de Symfony :

bin/console router:match /logout

:)

1 votes

Je pense que cette réponse est la plus simple et la plus propre pour faire le travail.

2 votes

Si vous voulez forcer la déconnexion d'un utilisateur malveillant, cela provoquera simplement une redirection. L'utilisateur malveillant pourrait simplement ignorer la réponse 302 et poursuivre son activité malveillante. Supposons qu'il essaie de changer le mot de passe d'un utilisateur connecté après un détournement de session réussi. S'il entre trois fois un mauvais mot de passe, il devrait être déconnecté, mais il peut ignorer la réponse 302 et essayer quand même, à moins que vous ne vérifiiez en plus le nombre de tentatives erronées. Conclusion : Vous ne pouvez pas imposer une déconnexion de cette manière.

9voto

Yasas Rangika Points 66

Nous devons définir l'utilisateur comme un utilisateur anonyme lors de la déconnexion. Ensuite, nous pouvons utiliser
$token->getUser()->getRoles(); dans le contrôleur ou {% if is_granted('ROLE_USER') %} dans le modèle de brindille.

use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
...
//$providerKey = $this->container->getParameter('fos_user.firewall_name');
$token = new AnonymousToken($providerKey, 'anon.');
$this->get('security.context')->setToken($token);
$this->get('request')->getSession()->invalidate();

0 votes

Ceci est particulièrement utile si vous voulez éviter que l'utilisateur soit obligé de se réauthentifier après la déconnexion ! Dans un cas simple, la clé du fournisseur est juste le nom de votre pare-feu (voir security.yml ).

2voto

Volmarg Reiso Points 51

Dans Symfony 4/5, c'est juste suffisant pour supprimer l'utilisateur :

    /**
     * @var TokenStorageInterface $token_storage
     */
    private TokenStorageInterface $token_storage;

    /**
     * Will force logout from system
     */
    public function logoutCurrentlyLoggedInUser()
    {
        $this->token_storage->setToken(null);
    }

Maintenant vous pouvez créer une méthode pour l'utiliser plus tard pour vérifier si l'utilisateur est connecté :

class Application extends AbstractController {...

    /**
     * Returns currently logged in user
     * @return object|UserInterface|null
     */
    public function getCurrentlyLoggedInUser()
    {
        return $this->getUser();
    }

1voto

Lynx_BY Points 71

Si la fonctionnalité rememberme est activée pour votre site, vous devez également nettoyer le cookie rememberme :

    $this->get('security.context')->setToken(null);
    $this->get('request')->getSession()->invalidate();

    $response = new RedirectResponse($this->generateUrl('dn_send_me_the_bundle_confirm', array(
                'token' => $token
                )));
    // Clearing the cookies.
    $cookieNames = [
        $this->container->getParameter('session.name'),
        $this->container->getParameter('session.remember_me.name'),
    ];
    foreach ($cookieNames as $cookieName) {
        $response->headers->clearCookie($cookieName);
    }

0 votes

Je ne sais pas pourquoi il n'a pas été davantage mis en avant, l'ajout de clearcookie est intéressant. (et fonctionne)

0 votes

Parce que ça ne marche pas. Mettre le jeton à null ne désauthentifie pas vraiment l'utilisateur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X