Navigation

Related Articles

Back to Latest Articles

Utilisation de sfDoctrineGuardPlugin pour la gestion des utilisateurs


Samuel Breton
Utilisation de sfDoctrineGuardPlugin pour la...

sfDoctrineGuardPlugin comme son nom l’indique est la version Doctrine de sfGuardPlugin qui est THE plugin de gestion des utilisateurs de Symfony.

Il comporte des formulaires d’identification et d’inscription très basique, mais son principal point fort est la gestion des droits associés aux utilisateurs, la possibilité de gérer des groupes le tout générant automatiquement les crédentials qui va permettre de sécuriser l’application de manière très simple.

Je ne reviendrai pas sur la gestion des crédentials qui est très bien expliquée dans le Jobeet #13.

De même pour l’installation. Le readme est très bien fait et explique très clairement comment faire.

Le modèle de données

Le modèle de données du plugin comporte la table des Utilisateurs, des Groupes et des Permissions ainsi que les tables d’associations entre Utilisateurs/Permissions, Groupes/Permissions et Utilsateurs/Groupes.

Ce sont les permissions attribuées à un utilisateur (directement ou par ses groupes) qui déterminent les crédentials qu’il aura une fois logué (C’est le nom de la permission qui sera le nom du crédential).

Pour illustrer tout ca, on va voir un petit exemple.

On prends une structure simple, avec 2 groupes et 3 permissions.
Les permissions de Lecture, Ecriture et Téléchargement (même si la loi Hadopie a été votée ^^).
Les groupes Admin qui a tous les droits et Membre qui n’a que le droit de lecture.

 
sfGuardPermission:
  pLecture:
    name: lecture
  pEcriture:
    name: ecriture
  pTelegargement:
    name: telechargement
 
sfGuardGroup:
  gAdmin:
    name: admin
  gMembre:
    name: membre
 
sfGuardGroupPermission:
  gp1:
    sfGuardGroup:      gAdmin
    sfGuardPermission: pLecture
  gp2:
    sfGuardGroup:      gAdmin
    sfGuardPermission: pEcriture
  gp3:
    sfGuardGroup:      gAdmin
    sfGuardPermission: pTelegargement
  gp4:
    sfGuardGroup:      gMembre
    sfGuardPermission: pLecture

Et 3 utilisateurs : Toto, Titi et Tata à qui on va définir des droits différents.

– Toto sera dans le groupe admin, il aura ainsi tout les droits.
– Titi et Tata seront dans le groupe Membre et auront ainsi seulement le droit de Lecture.
– Titi a en plus le droit de téléchargement.

Ce qui se traduit en fixture comme ceci :

 
sfGuardUser:
  Toto:
    username: toto
    password: t0t0
  Titi:
    username: titi
    password: t1t1
  Tata:
    username: tata
    password: t4t4
 
sfGuardUserGroup:
  ug1:
    sfGuardUser:  Toto
    sfGuardGroup: gAdmin
  ug2:
    sfGuardUser:  Titi
    sfGuardGroup: gMembre
  ug3:
    sfGuardUser:  Tata
    sfGuardGroup: gMembre
 
sfGuardUserPermission:
  up1:
    sfGuardUser:       Titi
    sfGuardPermission: pTelegargement

Dans un module lambda, on peut donc très facilement sécuriser nos pages comme suit.

/module/config/security.yml

secure:
  is_secure:   on
 
telechargement:
  is_secure:   on
  credentials: [lecture, telechargement]
 
default:
  is_secure:   off

La page secure nécessite que l’utilisateur soit connecté mais il n’y a aucune restriction de crédential. Les 3 utilisateur, une fois logés, pourront y accéder.

La page téléchargement nécessite 2 permissions lecture et téléchargement. Seuls Toto et Titi y auront accès. Tata sera redirigé automatiquement vers la page d’erreur de permissions.

La redirection après l’authentification.

L’authentification est gérée par le plugin, il suffit d’envoyer l’utilisateur vers la route @sf_guard_signin.

Une fois l’authentification effectuée, le script redirige l’utilisateur. Par défaut l’utilisateur est redirigé vers le HTTP_REFERER.

Heureusement on peut aussi déterminer une route vers laquelle on veut être redirigé après l’authentification de plusieurs manières.

Premièrement via des variable du app.yml

all:
  sf_guard_plugin:
    success_signin_url:      @my_route?param=value
    success_signout_url:     module/action

Autre méthode qui consiste à utiliser le comportement par défaut de redirection vers le referer, mais en utilisant la méthode setReferer() de la classe sfGuardSecurityUser.

<?php
class moduleActions extends sfActions
{
  ...
  public function executeAction(sfWebRequest $request)
  {
    ...
    $this->getUser()->setReferer('@my_route');
    $this->redirect('@sf_guard_signin');
  }
}

L’ordre de priorité est :
– la variable du fichier app.yml
– le getReferer() du GuardUser
– le HTTP_REFERER

Connecter automatiquement un utilisateur

Il est possible de connecter automatiquement un utilisateur grâce à la méthode signin() à la quelle on doit passer une instance de sfGuardUser.

Par exemple dans une action quelconque :

<?php
class moduleActions extends sfActions
{
  ...
  public function executeAction(sfWebRequest $request)
  {
    ...
    $utilisateur = Doctrine::getTable('sfGuardUser')->findOneByUsername('toto');
    $this->getUser()->signin($utilisateur);
    ...
  }
}

Associer un ou plusieurs groupes à un utilisateur

On a vu au début de l’article comment associer des groupes aux utilisateurs par le fixture.

On va voir ici comment le faire en php.

Par exemple si on avait à le faire dans le script d’inscription et qu’on veulait associer automatiquement le groupe membre aux utilisateurs qui s’inscrivent.

 
public function executeInscription(sfWebRequest $request)
{
  $this->form = new sfGuardUserFormRegister();
  // la classe de formulaire sfGuardUserFormRegister n'existe pas dans le plugin par defaut
  // je la mets en annexe à la fin de l'article
 
  if($request->isMethod('post'))
  {
    $this->form->bind($request->getParameter($this->form->getName()));
 
    if($this->form->isValid())
    {
      $permission = Doctrine::getTable('sfGuardGroup')->findOneByName('membre');
 
      $utilisateur = $this->form->getObject();
      $utilisateur['permissions'][] = $permission;
      $utilisateur->save();
 
      $this->getUser()->signIn($utilisateur);
      $this->redirect('@homepage');
    }
  }
}

Annexe

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
 
/**
 * formulaire d'inscription
 *
 * @package    form
 * @subpackage sfGuardUser
 * @author     Lexik
 * @version    SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
 */
class sfGuardUserFormRegister extends PluginsfGuardUserForm
{
 
  public function configure()
  {
    unset(
      $this['groups_list'],
      $this['permissions_list'],
      $this['algorithm'],
      $this['salt'],
      $this['is_active'],
      $this['is_super_admin'],
      $this['last_login'],
      $this['created_at'],
      $this['updated_at']
    );
 
    $this->widgetSchema['password']     = new sfWidgetFormInputPassword();
    $this->widgetSchema['password_bis'] = new sfWidgetFormInputPassword();
 
    $this->widgetSchema->setLabels(array(
      'username'     => 'Email* :',
      'password'     => 'Mot de passe* :',
      'password_bis' => 'Confirmation* :'
    ));
 
    $this->validatorSchema['username']     = new sfValidatorEmail(array('required' => true), array('invalid' => 'Cet email n\'est pas valide.', 'required' => 'Champ obligatoire.'));
    $this->validatorSchema['password']     = new sfValidatorString(array('required' => true, 'min_length' => 6), array('min_length' => '"%value%" est trop court (%min_length% lettres minimum).', 'required' => 'Champ obligatoire.'));
    $this->validatorSchema['password_bis'] = new sfValidatorString(array('required' => true, 'min_length' => 6), array('min_length' => '"%value%" est trop court (%min_length% lettres minimum).', 'required' => 'Champ obligatoire.'));
 
    $this->mergePostValidator(new sfValidatorSchemaCompare(
      'password',
      sfValidatorSchemaCompare::EQUAL,
      'password_bis',
      array(),
      array('invalid' => 'Les champs doivent être identiques.')
    ));
  }
 
}
Show Comments (8)

Comments

  • biowan

    Bonjour,

    Un site sympa pour les infos pratiques qui nous aident dans le développement de symfony. (j\’ai débuté depuis 3 semaines seulement)

    Il y a cependant un point que je constate sur plusieurs articles que j\’ai la peine à suivre. C\’est souvent juste noté \"… et dans le fichier de configuration …\" et on ne sait pas trop de quel fichier dont vous parlez. Dans cet article en question, je cherche la solution pour limiter les accès au niveau module. Au niveau applicative, il n\’y a pas de problème pour moi, mais je ne sais pas comment paramétrer pour les modules, c\’est peut-être juste un détail dont je n\’ai pas pu trouver l\’info.

    Donc, plus haut, vous avez mentionné \"Dans un module lambda, on peut donc très facilement sécuriser nos pages comme suit.\". Là, je n\’ai pas la moindre idée que quel fichier dont vous parlez. Enfin, ça ressemble en tout cas le fichier security.yml. Mais il s\’agit d\’un fichier au niveau applicatif et non au niveau du module.

    Pouvez-vous m\’éclaircir ce détail.
    1000 mercis.
    biowan

    • Article Author
  • magic001

    J\’ai installer le module sfDoctrineGuardPlugin et configurer l\’authentification, parcontre lorsque je veux acceder au module sfGuardUser, j\’ai ce message :\"Empty module and/or action after parsing the URL \"/sfGuardUser\" (/).\"
    j\’ai débuté depuis 1 mois, alors pouvez m\’éclaircir.

    Merci d\’avance.

    • Article Author
  • olivier

    @biowan : J’ai rajouté quelques précisions dans l’article qui je l’espère faciliterons la compréhension

    @magic001 : Ca ressemble à un problème de routing. Avez vous activé le plugin dans votre ProjectConfiguration.class.php ?

    • Article Author
  • Nicolas Pajon

    Bonjour et Merci pour les tuto,

    j’utilise ce plugin sur mon premier projet symfony et il ne manque qu’une seule chose: le changement de mot de passe utilisateur.

    je l’ai donc mis en place moi même mais j’ai un souci au niveau du validateur sur l’ancien mot de passe.

    • Article Author
  • Coco

    Bonsoir,

    bien que le post date un peu ; le contenu n’en est pas moins intéressant 🙂

    Cependant je me pose une question quant à l’utilisation de sfDoctrineGuardPlugin :

    Quel est le rapport entre la table créée par le plugin et une table déjà existante contenant les infos des membres (ou utilisateurs) ? Est-ce la même ? sinon comment faire pour « merger » leur contenu ?

    Si vous pouviez m’éclaircir sur ce point, ça serait top chouette 🙂
    Merci d’avance =)

    • Article Author
  • cyborg

    Bonjour petit probléme et j’ai besoin d’aide
    j’ai un message d’erreur qui s’affiche et je n’arrive pas a comprendre comment faire pour faire fonctionné le message c sa :
     » Unknown record property / related component « sfguardgroup » on « sfGuardGroupPermission »
    « 

    • Article Author
  • mahassen

    Bonjour,je vous remercie pour le tutoriel qui est super Intéressant.
    J’ai besoin d’utiliser ce plugin dans mon portail dont je suis entrain de développer ,mais j’ai besoin encore de vos commentaires et vos conseils pour que je puisse avancer dessus.

    En effet,je veux réaliser un portail(interface de connexion)qui fait la liaison entre différents sites joomla.Je m’explique:lorsqu’un utilisateur se connecte au portail alors la liste des sites joomla dont il est membre s’affiche et il clique sur le lien du site joomla

    • Article Author
  • mahassen

    excusez moi car mon commentaire n\’est pas encore terminé.
    Je m’explique:lorsqu’un utilisateur se connecte au portail alors la liste des sites joomla dont il est membre s’affiche et il clique sur le lien du site joomla il sera envoyé directement à son site voulu.
    Mon probléme est que je n\’ai pas encore d\’idées comment faire la liaison entre les bases de données des sites joomla et celle du portail symfony.
    Pourriez vous me conseiller pour savoir comment je peux résoudre ce probléme?
    Merci par avance

    • Article Author

Recevez nos articles