23 - Symfony : Gestion des utilisateurs
Objectifs
- ✅ Utiliser la commande
make:user, présentation de l'entité User. - ✅ Utilisation des fixtures pour créer différents Users.
- ✅ Créer un formulaire de login
- ✅ Ajouter une fonctionnalité de "déconnexion".
Pré-requis
Avoir terminé la quête
Introduction
User stories 📋
en tant que visiteur, je souhaite avoir accès à un formulaire d'inscription afin de pouvoir me créer un compte
In progress 🤸
en tant que visiteur, je souhaite me connecter
Doing 🏗️
création de l'entité User
création du formulaire de login
Done ✅
en tant que visiteur, je dois voir un visuel pour chaque acteur afin de pouvoir identifier plus facilement quelqu'un sans avoir à lire son nom.
Dans cette quête, tu vas aborder une notion très importante lors du développement d'une application : l’authentification. Et plus particulièrement, la gestion des utilisateurs.
Sommaire
Création des Users
Dans ton Wild Series, tu vas avoir besoin d'implémenter la notion d'utilisateur, "User" en anglais, pour plusieurs raisons :
-
D'une part, toutes les parties de ton site ne doivent pas être accessibles à tout le monde. Par exemple, le CRUD des séries ne sera accessible qu'à des utilisateurs authentifiés.
-
D'autre part, tu vas devoir définir "qui a écrit quoi" et le sauvegarder en base de données. Tu vas pouvoir ainsi intégrer la notion d'auteur au sein de ton Wild Séries.
Dans cette quête, tu vas principalement suivre les consignes de la documentation officielle. La gestion des utilisateurs se fait par le composant SecurityBundle, mais tu n'as pas à l'installer si tu as bien initialisé ton projet avec l'option --webapp (dans ce cas il est présent par défaut). Concentre toi sur la seconde partie concernant la création de l'entité User, en t'arrêtant bien aux migrations suite à la création de cette entité User !
Quand tu arrives au titre "Loading the User: The User Provider", ne va pas plus loin ! C'est le sujet de la suite de la quête.
Lors de la création de l'entité, conserve les options par défaut que te propose Symfony.
Ainsi, tu viens de générer une simple entité User, qui permettra de stocker les informations sur tes utilisateurs, au minimum leur identifiant et leur mot de passe. Si tu as besoin d'autres informations sur tes Users (nom, date de naissance, pays, etc.) tu peux simplement éditer la classe et y ajouter les propriétés voulues (N'oublie pas que tu peux utiliser la commande make:entity pour mettre à jour ton entité User).
Suis la documentation en partant de l'installation de SecurityBundle jusqu'à la migration de l'entité User
Un peu de sécurité
La gestion des utilisateurs demande un minimum de sécurité. Pour se connecter, ton User a généralement besoin d'un identifiant (par exemple un email ou nom d'utilisateur) et d'un mot de passe. Il existe d'autres stratégies d'identification (double authentification, biométrie, etc.) mais celles-ci sont plus complexes à mettre en place et ne seront pas traitées ici.
Tu dois te rappeler une règle essentielle : un mot de passe en base de données ne doit JAMAIS être stocké "en clair". Celui-ci doit systématiquement être encodé (via des algorithmes de hachage). Regarde cette vidéo jusqu'à 2'30 pour mieux comprendre ces fonctions. Il existe de nombreuses fonctions de hachage, plus ou moins performantes et sécurisées, de nouvelles sont régulièrement créées, apportant toujours plus de sécurité et de performance.

Lors de la tentative de connexion au site, le mot de passe saisi par l'utilisateur est haché par la fonction, et la chaîne ainsi obtenue est comparée à celle qui se trouve en base de données. Si les deux chaînes sont identiques, c'est que le bon mot de passe a été saisi et l'utilisateur est bien reconnu. Note bien qu'à aucun moment en tant que développeur, tu n'auras accès au mot de passe "en clair" de l'utilisateur. Si c'est le cas, c'est une grave faille de sécurité.
La sécurisation de l'authentification est un sujet complexe et critique. Heureusement, Symfony gère cela pour toi ! Le framework est même réglé par défaut pour utiliser la fonction de hachage la plus à jour. C'est le but du auto dans la partie password_hashers du fichier security.yaml.
À l'heure actuelle, en fonction de la version de PHP utilisée, ce sont les fonctions bcrypt ou argon2 qui sont utilisées par Symfony.
Utilisation des fixtures pour créer différents users.
Maintenant que ton application dispose d'une entité User et de son UserRepository associé, et que la base de données est mise à jour avec ces changements, tu vas pouvoir créer quelques utilisateurs dans ta table User. Pour cela, tu vas utiliser des fixtures. Commence par créer un fichier UserFixtures (via la commande make:fixtures) puis regarde la documentation sur le hashage de passwords
Tu vas créer deux faux utilisateurs (un contributeur et un admin), et ceux-ci auront un mot de passe. Cependant ce mot de passe devra être haché comme tout mot de passe, c'est le rôle du service $passwordHasher injecté dans le __construct en utilisant bien le type UserPasswordHasherInterface.
Suis bien la documentation, si tu rencontres des difficultés, une solution est disponible en cliquant ci-dessous.
Voir la solution
<?php
namespace App\DataFixtures;
use App\Entity\User;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
class UserFixtures extends Fixture
{
public function __construct(
private readonly UserPasswordHasherInterface $passwordHasher
) {
}
public function load(ObjectManager $manager): void
{
// Création d’un utilisateur de type “contributeur” (= auteur)
$contributor = new User();
$contributor->setEmail('contributor@monsite.com');
$contributor->setRoles(['ROLE_CONTRIBUTOR']);
$hashedPassword = $this->passwordHasher->hashPassword(
$contributor,
'contributorpassword'
);
$contributor->setPassword($hashedPassword);
$manager->persist($contributor);
// Création d’un utilisateur de type “administrateur”
$admin = new User();
$admin->setEmail('admin@monsite.com');
$admin->setRoles(['ROLE_ADMIN']);
$hashedPassword = $this->passwordHasher->hashPassword(
$admin,
'adminpassword'
);
$admin->setPassword($hashedPassword);
$manager->persist($admin);
// Sauvegarde des 2 nouveaux utilisateurs :
$manager->flush();
}
}
💻 Puis lance l'exécution de tes fixtures (pour rappel, cela vide par défaut toutes les tables de ta base de données, assure toi donc bien d'avoir des fixtures également pour les programmes, saisons, épisodes, etc. :
php bin/console doctrine:fixtures:load
Vérifie en base de données que tes utilisateurs sont bien créés. Si c'est bon, passe à la suite.
Gestion du login
Maintenant que tu disposes d'utilisateurs, il serait pertinent de pouvoir se connecter avec ces différents comptes. Pour cela, il faut une interface de connexion. Celle-ci se présente généralement sous la forme d'un formulaire d'authentification, avec un champ identifiant (login) et un champ mot de passe (”password”).
💻 Suis les consignes suivantes dans leur intégralité et reprends la configuration fournie par la documentation. N'oublie pas la partie sur la sécurisation CSRF.
Au niveau de la redirection après connexion, configure plutôt l'application pour rediriger l'utilisateur à l'accueil de ton Wild Séries.
Pour tester, ouvre la route /login dans ton navigateur et essaie de te connecter avec les différents comptes utilisateurs que tu as créé précédemment.
Si tout s'est bien passé, tu devrais, après identification, te retrouver à l'accueil de ton Wild Séries, avec, en bas de ta page, dans la barre de debug de Symfony, ton adresse email visible.

Si un jour tu as besoin d’ajouter un mot de passe directement en base de données, ne te lance pas dans le chiffrement “de tête” de celui-ci ! Tu peux utiliser cette commande présentée dans cette ressource.
Ajout du logout
Maintenant qu'un utilisateur peut se connecter, il doit pouvoir se déconnecter. Ce serait une faille de sécurité importante s'il n'était pas possible à un utilisateur de fermer sa session. Cela voudrait dire que, si tu te connectes à un site sur ordinateur ou un smartphone partagé, n'importe qui ayant accès à ce support pourrait utiliser ton profil sur cette application.
💻 Lis la documentation à ce sujet , et suis à la lettre les instructions afin d'ajouter cette fonctionnalité.
Un peu de mise en forme à tout ça !
Tu es arrivé jusqu'ici, bravo ! Mais ce n'est pas fini ! Tu disposes de fonctionnalités assez complètes, mais il manque un peu de liant à tout ça. Que dirais-tu de permettre à tous tes utilisateurs d'accéder facilement à l’ensemble de ces fonctionnalités ?
Cela peut se faire assez simplement en affichant un bouton connexion/déconnexion dans ta navbar
Pour cela, il te suffit d'ajouter ce fragment de code Twig :
{% if app.user %}
{{ app.user.email }}
<a href="{{ path('app_logout') }}"> Se déconnecter</a>
{% else %}
<a href="{{ path('login') }}"> Se connecter</a>
{% endif %}
Car oui, depuis Twig, tu as accès à app.user, une variable dite "globale", qui contient toutes les informations de l'utilisateur actuellement authentifié.
Essentiel pour le challenge : pour récupérer les informations de l'utilisateur depuis un contrôleur.
Toutes les infos disponibles en permanence dans Twig.
Conclusion
Pour résumer, dans cette quête, tu as effectué beaucoup de travail avec quelques lignes de commandes et un peu d'ajustement. Imagine si tu avais dû réaliser tout ça à la main, dans un projet hors framework ! Encore une fois, tu vois l'intérêt d'utiliser un framework pour gagner du temps et de la sécurité. Et les avantages de le maîtriser, pour savoir où intervenir afin de rendre ton code conforme à tes attentes.
💪 Challenge
Gestion des commentaires utilisateurs
Sur la page détail d’un épisode, tu dois ajouter la fonctionnalité “Laisser un commentaire”
User stories 📋
en tant que visiteur, je souhaite avoir accès à un formulaire d'inscription afin de pouvoir me créer un compte
In progress 🤸
en tant que visiteur identifié, je souhaite voir un formulaire afin de laisser un commentaire à propos d'un épisode
Doing 🏗️
Done ✅
en tant que visiteur, je souhaite me connecter
création de l'entité User
création du formulaire de login
À l’aide des compétences acquises jusqu’à présent, crée une entité Comment correspondant au fragment de modèle ci-dessous. Lors de la création de la relation avec l’entité User, ne choisis pas l’option par défaut, mais nomme explicitement ton champ author plutôt que user.
Tu peux constater que, dans le cadre d’une relation vers une entité donnée, tu n’es pas obligé de nommer la propriété correspondante de manière rigoureusement identique. Ainsi, la propriété “author” pointe vers l’entité “User”. Cela permet d’ajouter du sens à une relation. Cela permet aussi d’éviter les confusions quand une table est liée 2 fois à la même table. Par exemple, un commentaire sur Blablacar est relié 2 fois à la table
user: 1 fois pour le chauffeur, une fois pour le passager. Evidemment, tu n’auras pas oublié d’effectuer la migration en deux temps avecbin/console make:migration, suivi debin/console doctrine:migrations:migrate.
Ensuite, tu dois réaliser les fonctionnalités suivantes :
- Si un utilisateur est non connecté sur une page détail d’un épisode, la fonctionnalité “Ajouter un commentaire” n’est pas visible.
- Si un utilisateur est connecté sur une page détail d’un épisode, la fonctionnalité “Ajouter un commentaire” devient visible avec un formulaire composé d’un champ
rate, d’un champcommentet d’un bouton de soumission. - Lorsqu’un commentaire est ajouté par un utilisateur, celui-ci est bien enregistré comme auteur de celui-ci.
- Lorsqu’un commentaire est ajouté par un utilisateur, celui-ci est bien associé à l’épisode affiché.
- La liste des commentaires liés à la série est affichée dans l’ordre chronologique.
Tu l’auras compris, la relation entre le commentaire et l’épisode, ainsi que celle entre le commentaire et l’auteur, sont à faire du côté du contrôleur.
Critères de validation
- le formulaire de login est fonctionnel ;
- le lien de déconnexion est fonctionnel ;
- lorsque tu rédiges un commentaire, l’auteur actuellement connecté est bien associé en base de données ;
- lorsque tu rédiges un commentaire, la série est bien associée en base de données ;
- Les commentaires liés à l’épisode sont affichés dans l’ordre du plus vieux au plus récent ;
- Le code est disponible sur un repository GitHub, avec une branche correspondant à cette quête ;
Ressources partagées sur cette quête
- a partir de 16mn pour comprendre comment joindre un commentaire a un episode ou user.https://www.youtube.com/watch?v=aAderEVKLho&t=960s