Implémenter un UserProvider
Suite au premier article que j’avais rédigé pour mon entreprise qui mettait en avant l’utilisation de la sécurité (firewalls, authentification…), et d’un second article que j’ai rédigé sur ce propre article qui met en avant les méthodes permettant d’ajouter les fonctionnalités essentielles comme créer un compte, valider son compte, changer son mot de passe ou encore générer un nouveau mot de passe, j’ai décidé d’écrire un troisième et dernier article sur ce sujet, pour vous décrire comment implémenter son propre provider d’authentification.
Sommaire
À quoi sert un provider pour l’authentification ?
Le provider d’authentification est l’élément qui permet à un utilisateur qui souhaiterai s’authentifier d’être rattaché à un utilisateur d’une base de donnée ou dans renvoyé une erreur si les informations ne sont pas correctes. De base, Symfony2 propose un provider implémenter ce qui ne vous oblige pas à un implémenter un.
Pourquoi implémenter son propre provider
Implémenter son propre provider peut avoir plusieurs intérêts.
- Vous pourriez vouloir que votre utilisateur s’authentifie de plusieurs manières. Saisir son login, son username, son email ou tout autre information unique pourrait être utile.
- Nous pourrions aussi vouloir gérer les authentifications. Par exemple, un compte pourrait tout à fait exister mais celui-ci pourrait ne pas être activé, ou aurait pu être désactivé. Tous ces éléments peuvent rapidement être nécessaire pour le développer.
- Dans le cas d’une application sensible, on pourrait également vouloir envoyer un mail à la personne qui se connecte au compte, dans le but par exemple de détecter une activité suspecte.
- Toutes autres raisons…
Comment implémenter son provider
Sensio a mis en place pour son produit une interface rapide à implémenter. Il s’agit de UserProviderInterface.
Vous devrez implémenter trois méthodes :
- loadUserByUsername
- refreshUser
- supportsClass
loadUserByUsername permet de charger l’utilisateur correspondant aux informations données. C’est cette méthode qui est la plus importante pour nous. De là, vous pouvez charger l’utilisateur selon les règles que vous souhaitez pour votre application mais vous également lever moultes exceptions pour restreindre l’accès. Voici la liste complète des exceptions que vous pourrez levé. - BadCredentialsException est l’exception que vous risquez d’utiliser le plus. Elle doit vous permettre de déclarer à la personne qui tente de se connecter que les informations saisies ne correspondent à aucune entité en base de donnée.
- DisabledException sera levé si un compte qui aurait été désactivé par un administrateur tente d’être contacté. Cela pourrait être nécessaire si le compte requiert une validation par mail du compte par exemple.
- LockedException ressemble fortement à l’exception précédente DisabledException et sera créée dans le cas où le compte aurait été bloqué définitivement.
Toutes les autres exceptions peuvent avoir un rôle dans votre application. Toutes les descriptions vous permettrons de savoir laquelle peut vous servir dans telle ou telle cas.
Code d’un UserProvider
loadUserByUsername implémentation
|
|
Dans cette implémentation, nous cherchons un utilisateur qui pourrait avoir comme username ou comme mail l’objet $username qui a été passé en paramètre à la méthode.
Si aucune entité ne correspond à ma recherche, une exception UsernameNotFoundException sera levé.
Si un utilisateur a été trouvé, nous allons regardé si son compte est actif. Dans un autre cas, on lèvera une exception pour informer l’utilisateur du problème qui l’empêche de se connecter.
Si on souhaite connecter un utilisateur, il nous suffit juste de renvoyer l’objet (à condition qu’il implémente bien l’interface UserInterface).
refreshUser implémentation
Cette méthode est rapide à implementer dans mon cas et je ne vois pas de raison que son comportement change mais libre à vous de modifier cette méthode pour qu’elle réponde à vos besoins.
Elle doit regarder si l’objet correspond bien au type d’instance qu’on gère. Dans ce cas, on appelle loadUserByUsername.
supportsClass implémentation
Cette méthode renvoie un booléen, si le type de l’objet donnée est supporté.
Déclarer et utiliser son propre provider
Avant cela, si vous aviez suivis mon premier article sur comment utiliser l’authentification nativement dans Symfony2, vous devriez avois déclarer dans votre ficher app/config/security.ml, un provider comme ceci.
|
|
Si vous voulez utilisez un provider que vous auriez implémenter voici les deux déclarations à réaliser.
Déclarer le provider comme un service
On commence par déclarer le provider comme un service. Dans mon cas, j’injecte mon manager doctrine pour réaliser mes recherches grâce à l’ORM. Vous pourriez vouloir injecter d’autres services. Je vous conseille donc de suivre ces petits conseilles d’injection des dépendances.
|
|
Déclarer le provider que l’on souhaite utiliser
Désormais que votre provider est déclarer, nous allons demander au firewall qui s’occupe de la gestion des utilisateurs pour notre cas, de ce servir du service ayant pour id _securityuserprovider.
|
|
Conclusion
L’implémentation d’un provider d’authentification est très simple a réalisé et peu nous permettre de réaliser un code propre. L’intégralité de la documentation Symfony est disponible ici.
Vous pouvez retrouver le code utiliser dans le Gist qui suit.
|
|