Série – Créez un blog avec Symfony

#3 Sécurisez votre site avec Symfony

Apprenez à restreindre l'accès aux ressources sensibles de votre site

8 oct. 2020 à 11:59 – 7min


Table des matières

Bonjour et bienvenue dans ce nouvel article concernant la création d'un blog avec Symfony. Aujourd'hui, nous allons nous occuper de sécuriser notre interface d'administration que nous venons de créer avec EasyAdmin, mais sâchez que ce tutorial reste valable pour n'importe quel autre type de projet. 

Le composant security de Symfony

Pour commencer, nous allons intégrer à notre projet le composant security de Symfony, qui comme son nom l'indique, va nous permettre de sécuriser efficacement notre site :

symfony composer require security

Une fois le bundle installé, vous remarquerez qu'un fichier de configuration security.yaml vient d'être créé dans le répertoire config/packages. Ne vous inquiétez pas, nous y reviendrons plus tard. 

Dans notre exemple de blog, nous voulons faire en sorte qu'un utilisateur autorisé, par exemple un administrateur ou un auteur, puisse se connecter au site grâce à ses propres identifiants, afin de pouvoir accéder à l'interface d'administration via l'URL /admin. Nous ferons également en sorte que n'importe quel utilisateur puisse créer un nouveau compte avec des droits limités.

Pour ce faire, il faut commencer par créer une nouvelle entité User qui représentera un utilisateur. Pas besoin de le faire à la main, le bundle security intégère une nouvelle commande :

symfony console make:user

Laissez les valeurs par défaut, validez, puis effectuez une nouvelle migration Doctrine. 

Votre utilisateur est créé, il faut maintenant faire en sorte de pouvoir en créer de nouveaux.

Authentifier un utilisateur

Afin de s'authentifier, nous voudrions qu'un formulaire de connexion soit accessible via l'URL /login. Pas besoin de tout faire à la main, tapez simplement la commande suivante :

symfony console make:auth

Symfony vous demandera dans un premier temps de lui indiquer le type d'authentification que vous souhaitez proposer à vos utilisateurs. Nous choisissons ici le Login form authenticator. Il vous sera ensuite demandé d'indiqué le du controller chargé de l'authentification à créer. Nous choisissons ici LoginFormAuthenticator. Enfin, laissez les autres valeurs par défaut puis validez.

Vous pouvez maintenant accéder à la page /login, et magie ! Un formulaire de connexion apparaît ! Pour l'instant, vous ne pourrez pas en faire grand chose puisque vous n'avez pas encore créer d'utilisateur.

Enregistrer un nouvel utilisateur

Là encore, vous pourriez être tenté de créer un formulaire à la main pour enregistrer un nouvel utilisateur, mais le bundle security nous facilite la vie. Tapez simplement la commande suivante : 

symfony console make:registration-fom

Lorsqu'il vous sera demandé si vous souhaitez envoyer un email de vérification à l'utilisateur après la création de son compte, tapez "no". Nous y reviendrons dans un prochain article :). Pour le reste, vous pouvez laisser les valeurs par défaut. 

Maintenant, accédez à la page /register, un formulaire de création de compte vous attend !

Vous pouvez essayer par vous-même en créant un nouvel utilisateur, puis en vous connectant via la page /login. Si tout se passe "bien", vous devriez rencontrer une erreur. Ne paniquez pas, c'est tout à fait normal. Symfony vous demande simplement de préciser vers quelle URL l'utilisateur doit être redirigé après sa connexion. Rendez-vous dans le fichier src/Security/SecurityController.php, et modifiez la fonction onAuthenticationSuccess :

Dans notre exemple, nous redirigons l'utilisateur authentifié vers la page ... login. Bon, je vous l'accorde ce n'est pas très utile, mais nous n'avons pas d'autre page sur notre site pour le moment. Dans un cas d'utilisation réel, vous seriez tenter de modifier cette route par votre page d'accueil ou la page de profil de l'utilisateur. Mais pour cette démonstration, ça fera l'affaire.

Voilà, vous avez créé un système d'authentification complexe et sécurisé en ne tapant qu'une seule ligne de code ! 

Sécurisez l'accès à vos pages

Maintenant, nous allons faire en sorte que l'accès à certaines pages soit restraint. Mais avant de vous montrer comment faire, je dois vous expliquer un aspect important du bundle security : les rôles.

Si vous regardez votre entité User créée précédemment, vous verrez un champ "roles" de type array. Ce champ permet d'attribuer des rôles différent pour nos utilisateurs. Par exemple, en tant qu'administrateur du site, vous devriez un rôle "ROLE_ADMIN", tandis qu'un utilisateur authentifié lambda ne devra disposer que du rôle "ROLE_USER". En se basant sur le rôle de l'utilisateur courant, nous pouvons donc restreindre ou non l'accès à certaines ressources. Par exemple, nous voulons faire en sorte que toutes les URLs préfixées par /admin ne soient accessibles que par les utilisateurs disposant du rôle "ROLE_ADMIN". 

Pour cela, rendez-vous dans le fichier config/packages/security.yaml, et ajoutez les lignes suivantes : 

Le paramètre role_hierarchy permet de définir une hiérarchie des rôles. Dans notre exemple, nous indiquons qu'un utilisateur avec le rôle "ROLE_ADMIN", aura, en plus des droits liés à son rôle, les mêmes droits qu'un utilisateur normal. Enfin, le paramètre access_control permet de restreindre l'accès à certaines routes selon les droits de l'utilisateur courant. Ici, nous avons restreint les routes commençant par /admin aux utilisateurs disposant du rôle "ROLE_ADMIN" (remarquez ici la syntaxe regex).

Il est également possible de restreindre l'accès à une ressource depuis un controller, mais je vous déconseille de le faire si vous n'en avez pas explicitement besoin. Selon moi, il vaut mieux garder toute votre logique de sécurité au sein du même fichier plutôt que de s'éparpiller. Si vous en avez tout de même besoin, voici un exemple :

Essayez maintenant d'accéder à la page /admin, l'accès vous est maintenant bloqué !

Créer un administrateur depuis la ligne de commande

Ici, je vais vous montrer comment créer notre premier administrateur depuis votre ligne de commande, sans besoin d'être authentifié donc. Pour cela, nous allons créer une nouvelle commande Symfony : 

symfony console make:commande app:user:create 

Et qui contient le code suivant :

Nous n'allons pas ici nous attarder sur le code de cette commande puisqu'il reste assez trivial, et que les seules difficultés résident dans la création de commande Symfony auquel un article entier devrait bientôt être dédié.

Vous pouvez maintenant utiliser la commande suivante :

symfony console app:user:create 

Indiquez une adresse email ainsi qu'un mot de passe (attention, celui-ci sera affiché en clair dans la console), et votre nouvel administrateur sera créé. Vous pouvez maintenant vous connecter avec ce compte et accéder sans problème à votre interface d'administration !