Séance 10 : Sécurité
La documentation officielle : https://symfony.com/doc/current/security.html
Introduction
Deux notions majeures interviennent dans la conception de sécurité de Symfony :
Authentification : Qui êtes vous ? ; vous pouvez vous authentifier de plusieurs manières (HTTP authentification, certificat, formulaire de login, API, OAuth etc)
Authorization : Avez vous accès à ? ; permet d'autoriser de faire telle ou telle action ou accéder à telle page sans forcément savoir qui vous êtes, utilisateur anonyme par exemple.
Pour fonctionner, il est nécessaire d'ajouter le composant security à votre symfony.
Si vous avez installé le projet avec la version complète (webapp), cette ligne n'est pas nécessaire.
La sécurité dans symfony implique plusieurs éléments :
Le firewall: qui est la porte d'entrée pour le système d'authentification, on définit différents firewall (au minimum 1 seul) qui va permettre de mettre en place le bon système de connexion pour l'url spécifiée via un pattern.
Le provider : qui permet au firewall d'interroger une collection d'utilisateurs/mot de passe ; C'est une sorte de base de tous les utilisateurs avec les mots de passe. Il existe deux type par défaut :
in memory : directement dans le fichier security.yml mais du coup les hash des mots de passes sont disponible dans un fichier
Entity : N'importe quelle entité qui implémente à minima les deux interfaces
Enfin, plusieurs providers peuvent fonctionner en même temps par exemple in_memory et entity voire plusieurs entités simultanément. http://symfony.com/doc/current/security/entity_provider.html
Un encoder : qui permet de générer des hashs/d'encoder des mots de passe ; le plus connu étant MD5 mais vous pouvez utiliser d'autres encoders tels que : sha1, bcrypt ou plaintext (qui n'encode rien c'est le mot de passe en clair) http://symfony.com/doc/current/security/named_encoders.html
Les rôles : qui permettent de définir le niveau d'accès des utilisateurs connectés (authentifiés) et de configurer le firewall en fonction de ces rôles. Les rôles peuvent être hierarchisées afin d'expliquer par exemple qu'un administrateur (ROLE_ADMIN par exemple) et avant tout un utilisateur (ROLE_USER).
Le "guard" ou "authenticator" qui va gérer l'authentification, au travers de "passport". Il va par exemple vérifier que le couple login/mot de passe existe dans l'un des provider.
Configuration
A partir de la version 4, et avec le composant "maker", la gestion de la sécurité a été grandement facilitée. Là où sur les précédentes versions (la 2 notamment), il était d'usage de passer par un bundle tierce (FOSUserBundle par exemple), aujourd'hui cela n'est plus nécessaire.
Créer sa classe User
Si vous ne disposez pas encore d'une classe permettant la gestion des utilisateurs, il est possible d'en créer une avec la console. Si vous disposez déjà d'une classe utilisateur (ou que vous souhaitez utiliser plusieurs entités, il faudra modifier votre code en implémentant les interfaces UserInterface, PasswordAuthenticatedUserInterface
et en implémentant les méthodes imposées par ces interfaces).
L'instruction ci-dessous permet de lancer la console pour créer la table User.
Symfony va vous poser plusieurs questions afin de configurer les éléments (le nom de l'entité, si vous utilisez doctrine, le champ correspondant au login, et l'encodage du password.
Une fois cette commande exécutée vous avez un fichier d'entité de créé, un repository associé, et le fichier security.yaml (dans config) qui a été mis à jour.
Le fichier entité
Le fichier security.yaml
Ce fichier fait le lien avec l'entité User (le provider), le login retenu (ici un email), et l'encodage du mot de passe, par défaut "auto"
Mise à jour de la BDD
Il faut ensuite mettre à jour votre base de données, avec les commandes suivantes:
Créer la partie connexion
Une nouvelle fois la console va nous permettre de dégrossir le travail et produire le contrôleur, le fichier de configuration et le formulaire de connexion.
Pour le résultat ci-dessous.
Cette commande, comme indiqué génère plusieurs fichiers :
LoginAuthenticator.php : qui explique comment on authentifie un utilisateur (au travers de passeport)
SecurityController.php : Car ici, nous avons choisi une connexion avec formulaire, ce contrôleur permettra d'afficher la page de login, de récupérer les informations et de gérer la déconnexion
login.html.twig : qui contient le formulaire
Le fichier security.yaml est mis à jour pour faire le lien avec cet authenticator.
LoginAuthenticator
Attention !! Il faut modifier la ligne 51 avec une route qui existe dans votre projet
SecurityController
login.html.twig
Security.yaml mis à jour
La partie firewall est modifiée pour indiqué quel authenticator utiliser. On pourrait en avoir plusieurs.
Comme indiqué cette commande va créer plusieurs fichiers :
src/Security/LoginAuthenticator.php : qui va contenir la logique de votre authentification. Que faire une fois l'authetification réussie, ou en cas d'échec. Comment récupérer les informations de l'utilisateur.
src/Controller/SecurityController.php : qui va être le contrôleur gérant la partie sécurité et authentification. Par défaut la méthode login pour afficher le formulaire et traiter (avec l'aide de l'authenticator précédent), valider les données. C'est dans ce contraôleur que vous pouvez ajouter la déconnexion, l'enregistrement et le mot de passe perdu par exemple.
templates/security/login.html.twig : la vue contenant le formulaire de connexion, que vous pouvez librement adapter.
Mettre à jour le fichier security.yaml afin qu'il fasse le lien avec les différents éléments de sécurité.
Les étapes suivantes expliques ce qui a été créé.
Analyse du fichier security.yaml
Quasiment toute la sécurité se joue dans le fichier security.yaml qui fait le lien entre les différents éléments et gère les accès.
L'encodage du mot de passe (encoders) :
Tout est pré-confiuré, vous pouvez bien sûr adapter. L'encodage permet de définir le "format" de cryptage du mot de passe. Par défaut c'est "auto", c'est à dire que selon votre configuration Symfony choisira le niveau le plus élevé possible (bcrypt ou Argon2i)
Partie "User Provider" (providers) :
Le Provider permet de faire le lien avec une source de données contenant les couples login/mot de passe ou des clés d'API... Les providers peuvent être des entités, des données "in_memory", ... Cette partie est configurée a été configurée suite à la création de l'entité User, avec la méthode de connection (login), ici l'email sera utilisé. Il est possible de coupler plusieurs provider tant que l'email est unique sur l'ensemble des sources.
L'authentification et le firewall
C'est la partie essentielle du process de sécurisation. C'est lui qui permet de dire quand il faut vérifier et authentifier un utilisateur. Le firewall permet de déterminer pour un pattern d'url (une requête (request)), la méthode d'authentification à utiliser (une page de connexion, une clé d'API, une dépendance à un fournisseur OAuth, ...).
L'exemple ci-dessus permet de définir que pour les routes particulières (les assets, le profiler), il n'y a pas de vérification. Pour toutes les autres routes (main), il faudra utiliser le provider contenant nos User et l'authenticator gérant le formulaire de Login. C'est ici que l'on pourrait proposer plusieurs méthodes de connexion en ajoutant les authenticator adaptés.
Symfony propose des exemples pour de nombreuses méthodes d'authentification (login, ldap, json, ...) que vous trouverez sur la documentation officielle
La gestion des rôles et les autorisations
La gestion des roles se fait dans la partie "access_control" du fichier security. Il permet de définir pour chaque pattern d'URL quel rôle peut y accèder. C'est là que l'on sécurise nos différentes parties. Il est donc important de construire et structurer nos URL correctement pour être efficace sur le filtrage. Il faut évidemment veiller à ce que les pages de connexion ne soient pas derrière une page sécurisée...
Exemple:
De cette manière les URL seront automatiquement bloquées si l'utilisateur ne dispose pas du bon rôle. Il est aussi possible de tester ce rôle directement dans un contrôleur ou dans une vue selon les besoins. Voir la documentation pour plus d'éléments sur ce point
Récupérer l'utilisateur connecté
Enfin, il est souvent nécessaire de récupérer les informations sur l'utilisateur connecté. Pour cela, dans un contrô leur il est possible d'utiliser directement l'instruction :
Gérer la déconnexion
Sur la même idée que pour la connexion, il est possible de gérer la déconnexion. Pour cela, dans le fichier security.yaml, il faut définir le path (la route) pour la méthode qui gére la déconnexion, et la cible (une route, optionnelle), une fois la déconnexion réussie.
La méthode dans le contrôleur peut se résumer à :
Cette méthode qui ne retourne rien, permet la déconnexion, et la redirection se fait via le target définit dans security.yaml.
Générer un mot de passe avec le bon encodage
Grâce à la console, il est possible de générer un mot de passe selon l'encodage utilisé par Symfony.
Création d'un utilisateur
Il est possible d'ajouter des utilisateurs directement dans la base de données (par exemple avec PhpMyAdmin ou en mode console Mysql) avec le mot de passe encodé correctement ou alors en créant un formulaire d'inscription.
Dans la base de données
On va ajouter PhpMyAdmin à Docker, pour cela dans votre fichier docker-composer.yaml et ajouter les lignes ci-dessous :
Pour vous connecter http://localhost:8082, puis vos identifiants.
Dans la table User ajouter une entrée, avec un mot de passe crypté, et un rôle, qui doit être un tableau, exemple : ["ROLE_ADMIN"]
Attention ! On modifie le docker-compose.yaml MMI pas celui de Symfony !!!
Avec un formulaire d'inscription
La aussi le maker peut nous aider grandement...
bin/console make:registration
Répondez aux questions, il est nécessaire d'installer un complément si vous voulez vérifier le mail de vos utilisateurs : composer require symfonycasts/verify-email-bundle
Exercice
Mettre en place une classe User, et créer le formulaire de connexion en suivant la documentation (une commande dans le maker existe).
Ajouter une page qui ne sera accessible qu'a des utilisateurs Admin.
Vous pouvez ajouter une fonction pour récupérer le mot de passe perdu (une commande dans le maker existe...)
Dernière mise à jour
Cet article vous a-t-il été utile ?