Symfony : comment gérer l’apparition du panneau de connexion dans les zones rafraichies en Ajax

Symfony permet assez facilement de mettre en œuvre des appels Ajax afin de dynamiser vos écrans. Symfony permet également de facilement sécuriser tout ou partie de vos applications via de simples paramétrages. Si l’utilisateur connecté n’a pas le degré suffisant d’autorisation ou si sa session a expirée, il sera automatiquement dirigé, par le filtre de sécurité de Symfony, vers, par exemple, le panneau de login de votre application.

Un effet de bord de ces techniques est que, si l’utilisateur de votre application laisse sa session expirer, puis lance une action Ajax devant rafraichir une partie de son écran, il verra le panneau de connexion apparaitre dans cette zone : effet peu ergonomique garanti !

Voila la technique que j’utilise pour pallier à ce problème. A vrai dire, je ne sais pas si elle correspond à l’état de l’art, mais elle a l’avantage de bien fonctionner sans nécessiter de multiples interventions dans l’application.

1/ Permettre l’évaluation du Javascript dans les templates affichés via des appels AJax

Cela dépend de la librairie Javascript que vous utilisez. Par exemple, avec JQuery, il faudra préciser que le type de donnée retourné est ‘html’. Si vous utilisez les helpers Symfony, il vous faudra ajouter 'script' => true au tableau d’options passé au helper.

Cette étape n’est pas obligatoire. Elle permet toutefois de rediriger les utilisateurs en Javascript vers le panneau de connexion.


2/ Modifier le code du contrôleur gérant votre panneau de connexion

On va simplement lui dire que, si il est appelé via une requête Ajax, il n’utilise pas la vue habituelle.

Par exemple :

  /**
   * Executes login action
   *
   */
  public function executeLogin()
  {
    if($this->getRequest()->isXmlHttpRequest()) {
      $this->getResponse()->setStatusCode(401);
      return 'redirect';
    }
    /*
    end of the login action code
   */
  }

3/ Créer la vue appelée précédemment

Ici le fichier loginRedirect.php


La route correspondant à l’action de déconnexion @user_logout doit bien sur exister.

Voilà !

Et vous, que pensez vous de cette méthode ?

Publicités

10 réflexions au sujet de « Symfony : comment gérer l’apparition du panneau de connexion dans les zones rafraichies en Ajax »

  1. j0k3r

    Il me semble l’avoir déjà lu quelque part cette méthode.

    Mais pourquoi tu rediriges vers logout? Faudrait pas le renvoyer vers login plutôt ?

    Répondre
  2. Olivier Mansour

    Je n’ai pas précisé que je suis l’auteur de cette méthode – à vrai dire, tout mes collègues l’utilise donc il m’est difficile d’identifier un auteur précis.

    Dans l’exemple je redirige vers logout car on peut imaginer que l’action de déconnexion purge les variables de session et les cookies qui pourraient « trainer » et/ou affiche un message indiquant la déconnexion. Mais rediriger vers le login peut aussi fonctionner.

    Répondre
  3. Eric Lemoine

    Une autre solution est de traiter le code de retour HTTP côté JS pour faire une action particulière sur réception de code 401 et/ou 403 à l’appel d’une action en Ajax.
    Avec sfGuard les codes de retour 401 et 403 sont correctement gérés depuis le changeset suivant : http://trac.symfony-project.com/changeset/6066

    Avec prototype, par exemple, on pourrait faire :
    new Ajax.Request(‘/your/url’, {
    onComplete: function(transport) {
    if (401 == transport.status)
    // redirection vers le login
    }
    });

    Répondre
  4. Olivier Mansour

    oui, c’est la meilleure solution mais elle nécessite de faite ce travail sur chaque appel JS. Il suffit de l’oublier pour retrouver le pb exposé.

    L’idéal c’est de faire les deux peut être (sur l’affichage du panneau de connexion et les appels JS) ?

    Répondre
  5. Eric Lemoine

    On peut étendre la classe Ajax.Request afin d’y ajouter une méthode on401 qui sera automatiquement appelée par Prototype (ou une méthode onFailure plus générale avec traitement de l’attribut « status » de la réponse pour gérer les 401).

    Du coup on utilisera par exemple un new Ajax.SecureRequest() en lieu et place d’un Ajax.Request() pour les appels vers des pages sécurisées (ou pour tous les appels si on craint d’en oublier).

    Répondre
  6. Fabien Meynard

    Pourrais-tu donner un peu plus d’informations sur la partie 1/ ?
    En fait je ne vois pa ou je dois passer l’argument car visiblement chez cette étape est obligatoire.

    Merci d’avance
    Cordialement

    PS : Mon nom te dit surement quelque chose 🙂

    Répondre

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s