FAQ SymfonyConsultez toutes les FAQ
Nombre d'auteurs : 17, nombre de questions : 81, dernière mise à jour : 18 juin 2017 Ajouter une question
Les questions redondantes se multipliant sur le forum Symfony, nous avons choisi de créer cette FAQ afin de regrouper les questions qui sont posées fréquemment.
Vos remarques et idées sont les bienvenues. Et pourquoi pas votre aide ! S'il vous prend l'envie de tailler votre plus belle plume et de retrousser vos manches, il y a de quoi faire !
- Comment installer sfDoctrineGuardPlugin ?
- Que faire quand je reçois une erreur « Call to undefined method myUser::isAnonymous » après l'installation de sfDoctrineGuardPlugin?
- Comment créer sa propre méthode d'authentification pour sfDoctrineGuardPlugin ?
- Comment utiliser un système personnalisé d'authentification avec sfDoctrineGuard sans devoir remplir sa base avec tous les utilisateurs ?
- Comment gérer les changements de données avec un système personnalisé d'authentification avec sfDoctrineGuard ?
- Comment gérer les droits avec une authentification externe dans SfDoctrineGuard ?
Tout d'abord, commencez par l'installer par la méthode que vous préférez : ligne de commande, un checkout SVN ou manuellement, activez-le dans la configuration de votre projet et reconstruisez votre modèle.
Ensuite, activez ses modules au niveau de chacun des projets qui le requièrent. Pour une application frontend, vous n'aurez besoin que du module d'authentification ; pour le backend, vous voudrez probablement gérer les permissions et les utilisateurs. Pour ce faire, modifiez votre fichier settings.yml au niveau de chaque application.
Pour le backend :
.settings:
enabled_modules: [default, sfGuardGroup, sfGuardUser, sfGuardPermission]
.settings:
enabled_modules: [default, sfGuardAuth]
Vous pouvez additionnellement ajouter l'option « Se souvenir de moi » en modifiant votre fichier filters.yml comme suit, au niveau de chaque application à sécuriser :
class: sfGuardRememberMeFilter
security: ~
Maintenant, il faut que Symfony pense à utiliser sfDoctrineGuardPlugin pour les formulaires de connexion. À cette fin, ajoutez ces quelques lignes à votre fichier settings.yml, toujours dans l'application à sécuriser :
login_action: signin
secure_module: sfGuardAuth
secure_action: secure
{
}
url: /login
param: { module: sfGuardAuth, action: signin }
sf_guard_signout:
url: /logout
param: { module: sfGuardAuth, action: signout }
Finalement, il faut que votre application ou vos modules requièrent une authentification avant affichage pour que l'usage de ce plug-in soit utile. Ajoutez donc ces quelques lignes dans le fichier security.yml de l'application ou du module à sécuriser :
is_secure: true
Vérifiez que le module sfGuardAuth est bien activé, dans le fichier settings.yml :
{
}
user:
class: sfGuardSecurityUser
Il est fort possible que vous ne vouliez pas utiliser le système de sfDoctrineGuardPlugin pour la connexion, par exemple parce que vous avez déjà un système de SSO sur votre site, un serveur LDAP pour votre Intranet, etc. sfDoctrineGuardPlugin vous permet de définir une fonction entièrement personnalisée pour déterminer si un utilisateur est correctement authentifié ou non (si vous le voulez, elle peut renvoyer true à tous les utilisateurs, cette méthode n'est pas sans risque).
Vous devez fournir au plug-in une fonction ou une méthode qui, prenant le nom d'utilisateur et le mot de passe entré, renvoie un booléen disant si l'utilisateur a entré des identifiants corrects ou non. Nous développerons ici une classe possédant une méthode statique permettant le login d'un utilisateur.
Premièrement, créez un fichier myLogin.class.php dans le dossier lib de votre application. Voici sa structure :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | <?php class myLogin extends sfGuardSecurityUser { public static function checkPassword($username, $password) { if($username && $password) return true; } } |
Maintenant, il faut demander à sfDoctrineGuardPlugin d'utiliser cette méthode pour connecter vos utilisateurs. Cela se fait très simplement dans le fichier de configuration app.yml de votre application :
sf_guard_plugin:
check_password_callable: [myLogin, checkPassword]
sfDoctrineGuardPlugin souffre d'un grand défaut : pour qu'un utilisateur se connecte, il doit être en base de données, un point c'est tout. Que vous utilisiez une méthode de connexion autre ou non. Cependant, cela peut être détourné sans trop de difficultés. Notez qu'il est inutile de prévoir une méthode de connexion personnalisée, la partie du plug-in l'utilisant sera surchargée.
Tout d'abord, il faut changer un peu le formulaire de connexion pour ajouter notre validateur (qui sera montré juste après) dans la configuration. Notifions-en Symfony dans le fichier de configuration de l'application, app.yml :
sf_guard_plugin_signin_form: myAuthForm
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | <?php class myAuthForm extends sfGuardFormSignin { public function configure() { parent::configure(); $this->validatorSchema->setPostValidator(new sfGuardValidatorCustomUser()); } } |
sfDoctrineGuardPlugin recherche les utilisateurs par leur pseudo ; nous n'utiliserons que l'identifiant fourni par la méthode externe. Il ne requiert pas de mot de passe pour tenter de valider, nous le ferons.
Ce code est à compléter et à mettre dans un nouveau module sfGuardAuth (un simple dossier suffira), dossier lib, fichier sfGuardValidatorCustomUser.class.php.
Code : | Sélectionner tout |
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 50 51 52 53 | <?php class sfGuardValidatorCustomUser extends sfGuardValidatorUser { protected function doClean($values) { $username = isset($values[$this->getOption('username_field')]) ? $values[$this->getOption('username_field')] : ''; $password = isset($values[$this->getOption('password_field')]) ? $values[$this->getOption('password_field')] : ''; // don't allow to sign in with an empty username if ($username && $password) { // votre méthode de connexion, renvoie $connected si l'utilisateur est connecté // ainsi que toute la série de variables utilisées si l'utilisateur n'est pas déjà en base if($connected) { // récupérons manuellement si l'utilisateur est déjà en base, grâce à son identifiant $query = Doctrine_Core::getTable('sfGuardUser')->createQuery('u')->where('u.id = ?', $id); $user = $query->fetchOne(); // s'il n'est pas en base, ça ne tardera pas if(! $user) { $user = new sfGuardUser(); $user->setId($id); $user->setFirstName($prenom); $user->setLastName($nom); $user->setEmailAddress($email); $user->setUsername($pseudo); $user->setIsActive(true); $user->setIsSuperAdmin(false); $user->save(); // et l'utilisateur est dans la table ! } // on renvoie cet objet utilisateur avec les values passées en paramètre, comme l'original return array_merge($values, array('user' => $user)); } } // si tout ne s'est pas bien passé (pas de nom d'utilisateur, de mot de passe ou d'enregistrement dans la méthode externe) // on fait comme sfDoctrineGuardPlugin et on renvoie une belle exception if ($this->getOption('throw_global_error')) { throw new sfValidatorError($this, 'invalid'); } throw new sfValidatorErrorSchema($this, array($this->getOption('username_field') => new sfValidatorError($this, 'invalid'))); } } |
Quand l'utilisateur change certaines données sur le système de connexion centralisé, il est bien normal qu'elles soient mises à jour dans votre application. Le problème est que cela ne peut pas se faire tout seul, vous ne pouvez pas modifier le système de connexion pour qu'il vous en notifie.
La seule solution restante est de les modifier à chaque connexion. C'est là qu'il devient fort intéressant de référer aux utilisateurs par leur identifiant : ils peuvent changer de pseudo à volonté, leur identifiant ne changera jamais. Ils peuvent bien entendu changer d'autres propriétés, étant moins cruciales pour leur identification elles ne poseront pas de problème.
La plus simple technique à employer : si le pseudo (ou n'importe quelle autre donnée) change dans ce que le système externe d'authentification retourne par rapport à ce qui existe dans la base, alors il y a eu modification. Le code qui en découle est plus long et pénible à écrire que complexe, et se présente sous la forme suivante :
Code : | Sélectionner tout |
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 | if($user->getFirstName() != $prenom) { $user->setFirstName($prenom); $user->save(); } if($user->getLastName() != $nom) { $user->setLastName($nom); $user->save(); } if($user->getUsername() != $pseudo) { $user->setUsername($pseudo); $user->save(); } if($user->getEmailAddress() != $email) { $user->setEmailAddress($email); $user->save(); } |
Code : | Sélectionner tout |
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 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | <?php class sfGuardValidatorCustomUser extends sfGuardValidatorUser { protected function doClean($values) { $username = isset($values[$this->getOption('username_field')]) ? $values[$this->getOption('username_field')] : ''; $password = isset($values[$this->getOption('password_field')]) ? $values[$this->getOption('password_field')] : ''; // don't allow to sign in with an empty username if ($username && $password) { // votre méthode de connexion, renvoie $connected si l'utilisateur est connecté // ainsi que toute la série de variables utilisées si l'utilisateur n'est pas déjà en base // on récupère notamment $connected et $id if($connected) { // récupérons manuellement si l'utilisateur est déjà en base, grâce à son identifiant $query = Doctrine_Core::getTable('sfGuardUser')->createQuery('u')->where('u.id = ?', $id); $user = $query->fetchOne(); // s'il n'est pas en base, ça ne tardera pas if(! $user) { $user = new sfGuardUser(); $user->setId($id); $user->setFirstName($prenom); $user->setLastName($nom); $user->setEmailAddress($email); $user->setUsername($pseudo); $user->setIsActive(true); $user->setIsSuperAdmin(false); $user->save(); // et l'utilisateur est dans la table ! } else { if($user->getFirstName() != $prenom) { $user->setFirstName($prenom); $user->save(); } if($user->getLastName() != $nom) { $user->setLastName($nom); $user->save(); } if($user->getUsername() != $pseudo) { $user->setUsername($pseudo); $user->save(); } if($user->getEmailAddress() != $email) { $user->setEmailAddress($email); $user->save(); } } return array_merge($values, array('user' => $user)); } } if ($this->getOption('throw_global_error')) { throw new sfValidatorError($this, 'invalid'); } throw new sfValidatorErrorSchema($this, array($this->getOption('username_field') => new sfValidatorError($this, 'invalid'))); } } |
Il est fort probable que vous puissiez récupérer quelques droits de votre système d'authentification externe. Par exemple, une variable $r, indiquant si un utilisateur appartient ou non à un groupe donné, ce qui lui octroie certains droits. Imaginons que $r corresponde au groupe 42, il vous faudra alors ajouter ce code dans votre validateur personnalisé :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | if($r) { $perm = new sfGuardUserGroup(); $perm->setUserId($id); $perm->setGroupId(42); $perm->save(); } |
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 | if(! $r) { $q = Doctrine_Query::create() ->delete('sfGuardUserGroup u') ->where('u.user_id = ?', $id) ->andWhere('u.group_id'); $r->execute(); } |
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | foreach($groups as $group) { $q = Doctrine_Query::create() ->select('g.id') ->from('sfGuardGroup g') ->where('g.name = ?', $group); $grp = $r->fecthOne(); $perm = new sfGuardUserGroup(); $perm->setUser($user); $perm->setGroup($grp); $perm->save(); } |
Proposer une nouvelle réponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour çaLes sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.