Symfony: Réaliser une identification ajax avec sfDoctrineGuardPlugin

Dans cette publication, nous allons voir comment mettre en place un système d’identification basé sur le plugin sfDoctrineGuard. Pour que cela fonctionne, il vous faut également l’excellente librairie jquery. Dans cette article, je n’aborde pas l’installation du plugin, ni l’installation et le chargement de jquery.

Nous allons commencer par générer un nouveau module « user » dans notre projet avec la commande ci-dessous:

./symfony generate:module frontend user

Nous allons dès maintenant modifier notre module « user » pour y mettre notre propre code. Pour cela nous allons inclure la classe « BasesfGuardAuthActions » dans notre classe et changer l’extends:

require_once(sfConfig::get('sf_plugins_dir').'/sfDoctrineGuardPlugin/modules
/sfGuardAuth/lib/BasesfGuardAuthActions.class.php');

class userActions extends BasesfGuardAuthActions
{
  ...
}

J’avais un problème a résoudre lors de l’affichage de la page signin lors de l’appel d’une page protégée. J’ai choisi d’y mettre uniquement une information utilisateur lui indiquant de s’identifier avec le formulaire. J’ai créé le fichier signinSuccess.php dans le dossier templates.

Nous allons maintenant monter le formulaire d’identification dans un component.

class userComponents extends sfComponents
{
  public function executeSignin(sfWebRequest $request)
  {
    $class = sfConfig::get('app_sf_guard_plugin_signin_form', 'sfGuardFormSignin');
    $this->form = new $class();
  }
}

template: _signin.php

<div id="form_message">&nbsp;</div>
<form id="guard" action="<?php echo url_for('@sf_guard_signin') ?>" method="post">
  <?php echo $form->renderHiddenFields(); ?>
  <label>Utilisateur:</label>
  <?php echo $form['username']->render(); ?>
  <label>Mot de passe:</label>
  <?php echo $form['password']->render(); ?>
  <?php echo $form['remember']->render(array('id' => 'remember')); ?>
  Se souvenir de moi

  <input type="submit" value="S'identifier" />
  <a href="<?php echo url_for('@sf_guard_password') ?>">Mot de passe oublié ?</a>
</form>

<script type="text/javascript">
  $('#guard').submit(function() {
    $.post("<?php echo url_for('@sf_guard_signin'); ?>", $('#guard').serialize(), function(response) {
      switch(response.status) {
        case 'success':
        $('#form_message').html(response.message);
        $(location).attr('href',response.url);
        break;
        case 'failure':
        $('#form_message').html(response.message);
        $('#form_message').show();
        break;
      }
    }, 'json');
    return false;
  });
</script>

Nous allons rajouter un peu de css pour cacher notre zone « form_message »:

#form_message {
  display: none;
  font-weight: bold;
  color: red;
}

Prochaine phase, désactiver les routes et y mettre nos propres paramètres. Nous allons pour cela toucher 3 fichiers:

app.yml

all:
  sf_guard_plugin:
    routes_register: false

routing.yml

sf_guard_signin:
  url:      /login
  param:    { module: user, action: signin }

sf_guard_signout:
  url:      /logout
  param:    { module: user, action: signout }

sf_guard_password:
  url:      /password
  param:    { module: user, action: password }

settings.yml

all:
  .actions:
    login_module:           user
    login_action:           signin
        
    secure_module:          user
    secure_action:          secure

La dernière phase de cette réalisation est l’implémentation de notre fonction signin. Voici le code utilisé pour un dialogue ajax:

class userActions extends BasesfGuardAuthActions
{
  public function executeSignin($request)
  {
    $user = $this->getUser();
    if ($user->isAuthenticated())
    {
      return $this->redirect('@homepage');
    }

    if($request->isMethod('post') && $request->isXmlHttpRequest())
    {
      $class = sfConfig::get('app_sf_guard_plugin_signin_form', 'sfGuardFormSignin');
      $form = new $class();
      $form->bind($request->getParameter($form->getName()));
      if ($form->isValid())
      {
        $values = $form->getValues();
        $user->signin($values['user'], array_key_exists('remember', $values) ? $values['remember'] : false);
        $signinUrl = sfConfig::get('app_sf_guard_plugin_success_signin_url', $user->getReferer($request->getReferer()));

        return $this->renderText(json_encode(array('status' => 'success', 'url' => $signinUrl)));
      }
      else
      {
        return $this->renderText(json_encode(array('status' => 'failure','message' => 'Identification incorrecte')));
      }
    }

    $this->getResponse()->setStatusCode(401);
  }
}

Il nous reste plus qu’à insérer notre component dans notre layout ou notre template:

<?php if (!$sf_user->isAuthenticated()): ?>
<?php include_component('user', 'signin'); ?>
<?php endif; ?>

L’implémentation est terminée. J’espère que ce petit article vous permettra de mettre en place un formulaire à la web 2.0 😉

Share

11 réflexions sur « Symfony: Réaliser une identification ajax avec sfDoctrineGuardPlugin »

  1. Bonjour, j’ai suivis votre tuto à la lettre et malheureusement, je n’arrive pas a faire marcher malgré mes différentes recherches.
    Quand j’essaye de m’identifier avec un mauvais pass, je tombe sur le template signingSuccess du module « user » avec pour adresse http://www.monsite.com/login et quand j’essaye le bon pass même chose, rien ne s’affiche dans le div message, je ne vois vraiment pas où je me suis planté.
    Merci par avance de votre aide.

  2. Bonjour,
    J’ai essayé ce code. Il fonctionne très bien lorsque l’authentification échoue. En revanche, j’ai une erreur 500 lorsque l’identification est bonne.
    Je pense que c’est une bêtise mais je n’arrive pas à trouver.
     
    merci par avance

  3. Bonjour,
    Après avoir réalisé les opérations décrites si dessus, j’obtiens une erreur ;
    The component does not exist: « sfGuardAuth », « signin ».
     
    Il me semble que ce sont les fichiers du plugins qui sont appelés alors que dans le cas présent on re-déclare ces fichiers dans le module de l’application
    Une idée du fichier à modifier ?

  4. Pour éviter de revenir à la page d’accueil à chaque fois qu’on se connecte sur une page, dans certains cas, il est plus confortable de juste réafficher la page où l’utilisateur est présent. Pour cela, j’ai modifié la classe userActions

    06 if ($user->isAuthenticated())
    07 {
    08 return $this->redirect(‘@homepage’);
    09 }

    PAR

    if ($user->isAuthenticated()) {
    return $this->redirect($_SERVER[‘HTTP_REFERER’]);
    }

    Maintentant ton exemple est au poil 😉

    • Bonjour,
      Comme j’utilise un component pour afficher mon formulaire, le contenu du form est dans le fichier _signin.php. Vous le trouvez dans le tutorial.

  5. Bonjour,
    Merci pour cette petite astuce qui sera forte utile !

    J’ai juste une petite question concernant la validation des erreurs : si la personne ne saisit pas de mot de passe, qu’y a-t-il comme erreur d’indiquée ? Identification incorrecte non ?

    Je trouve cela assez dommage de perdre le bénéfice des validateurs symfony pour placer un peu d’ajax qui au final, retire un peu d’interactivité alors qu’il est censé en ajouter :p

    Mais c’est mon point de vue 🙂

    • Vous avez toujours la possibilité de gérer les erreurs dans le retour json. Il suffit pour cela de personnaliser le cellule du tableau « message ».
      Dans mon cas, je préfère ne pas donner trop de renseignements sur le type d’erreur.

      • Bonjour Bertrand et merci pour l’article
        Je suis encore un novice en symfony et j’ai juste remarqué (d’après mes tests au moins!), que le code du toto ne permet pas de rediriger vers une page 401 en cas d’accès non autorisé à une ressource protégée
        n’avez vous pas pris en compte cette fonctionnalité ou c moi qui a un problème quelques parts ?

      • Bonjour,

        Si une ressource est protégée et que l’utilisateur n’est pas identifié, il sera redirigé vers l’action de login. Ce sont les options définies dans le fichier settings.yml. Par contre, s’il est identifié mais qu’il n’a pas les autorisations nécessaires, il sera aiguillé sur l’action secure également définie dans le fichier settings.yml. J’espère que cette explication est claire. A vous de réaliser cette action qui n’est pas décrite dans ce tuto.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *