Académique Documents
Professionnel Documents
Culture Documents
10 Sécurisez L'accès de Votre Site Web - Construisez Un Site Web À L'aide Du Framework Symfony 5 - OpenClassrooms
10 Sécurisez L'accès de Votre Site Web - Construisez Un Site Web À L'aide Du Framework Symfony 5 - OpenClassrooms
Accueil > Cours > Construisez un site web à l’aide du framework Symfony 5 > Sécurisez l'accès de votre site web
20 heures Moyenne
Mis à jour le 08/07/2022
04:23
À présent, il est temps de découvrir comment la sécurité est gérée avec Symfony. C'est une étape
un peu technique mais très importante et cela va nous permettre d'avoir un espace membre non
seulement fonctionnel mais également sécurisé !
Dans ce chapitre :
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre-… 1/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
C'est parti !
Le contrôle de la sécurité sous Symfony est très avancé mais également très simple. Pour cela
Symfony distingue :
l'authentification,
l'autorisation.
Prenons quelques minutes pour définir ces mécanismes, c'est important pour le reste du
chapitre.
L'authentification, c'est le procédé qui permet de déterminer qui est votre visiteur. Il y a deux cas
possibles :
Régler les paramètres du firewall va vous permettre de sécuriser le site. En effet, vous pouvez
restreindre l'accès à certaines parties du site uniquement aux visiteurs qui sont membres.
Autrement dit, il faudra que le visiteur soit authentifié pour que le firewall l'autorise à passer.
L'autorisation intervient après l'authentification. Comme son nom l'indique, c'est la procédure
qui va accorder les droits d'accès à un contenu. Sous Symfony, c'est l'access control qui prend en
charge l'autorisation.
Prenons l'exemple de différentes catégories de membres. Tous les visiteurs authentifiés ont le
droit de poster des messages sur le forum mais uniquement les membres administrateurs ont
des droits de modération et peuvent les supprimer. C'est l'access control qui permet de faire cela.
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre-… 2/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
Cas n°1 : Un utilisateur anonyme souhaite se rendre sur la page /foo . Cette page est
accessible sans identification.
Comme il n'est pas nécessaire d'avoir des droits spécifiques pour accéder à cette page, tous les
visiteurs vont y accéder après avoir passé le pare-feu.
Le schéma suivant montre les différentes étapes du mécanisme de sécurité et distingue la partie
"authentification" (le firewall) de la partie "autorisation ("access control") :
2. La configuration du pare-feu a été réalisée pour que cette page soit accessible sans
identification. Le visiteur peut donc passer.
3. L'access control, ou contrôle d'accès, vérifie si la page /foo demande des droits
particuliers. Ce n'est pas le cas donc le visiteur passe.
4. La page /foo s'affiche pour le visiteur.
Cas n°2 : Un utilisateur anonyme souhaite se rendre sur la page admin/foo . Cette
page demande des droits d'accès particulier.
Cette fois, notre visiteur anonyme souhaite afficher la page /admin/foo . Mais l'accès à cette
page est limité aux utilisateurs qui on un rôle ROLE_ADMIN. L'accès lui est donc refusé :
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre-… 3/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
Mécanisme de sécurité pour une page qui requiert des droits particuliers
: visiteur anonyme.
Cas n°3 : Un utilisateur identifié souhaite se rendre sur la page admin/foo . Cette page
demande des droits d'accès particulier.
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre-… 4/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
Mécanisme de sécurité pour une page qui requiert des droits particuliers
: visiteur identifié.
Cas n°4 : Un utilisateur identifié souhaite se rendre sur la page admin/foo . L'utilisateur
dispose des droits d'accès requis.
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre-… 5/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
Mécanisme de sécurité pour une page qui requiert des droits particuliers
: le visiteur a le rôle requis.
Récapitulatif
Le processus de sécurité suit toujours ces étapes mais le nature de l'authentification peut
varier. En effet, selon vos besoins, il existe de nombreuses manières d'authentifier les
visiteurs, (banal formulaire d'identification, authentification avec Google, etc). Il faut retenir
que la méthode choisie n'a pas d'incidence sur votre code.
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre-… 6/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
Passons à la pratique
Même si le mécanisme de sécurité est plutôt simple à appréhender, cela prend quand même un
peu temps à mettre en place. Procédons par étape !
Configurez la sécurité
L'importance de la sécurité est telle qu'il y a un fichier de configuration dédié ! C'est le
fichier security.yaml qui se trouve dans le répertoire config/packages de votre application. Pour
l'instant, il n'y a pas grand chose dedans. Nous allons déjà y ajouter ces sections (elles sont
décrites ensuite) :
yaml
1 # config/packages/security.yaml
2
3 security:
4 encoders:
5 Symfony\Component\Security\Core\User\User: plaintext
6
7 role_hierarchy:
8 ROLE_ADMIN: ROLE_USER
9 ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
10
11 providers:
12 in_memory:
13 memory:
14 users:
15 user: { password: userpass, roles: [ 'ROLE_USER' ] }
16 admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
17
18 firewalls:
19 dev:
20 pattern: ^/(_(profiler|wdt)|css|images|js)/
21 security: false
22
23 access_control:
24 #- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
25
La section de base se nomme security car c'est le nom que le bundle SecurityBundle
a retenu pour sa configuration. En effet, dans Symfony, la sécurité vient d'un bundle ! C'est
ce bundle que nous allons configurer.
Encoders
yaml
1 security:
2 encoders:
3 Symfony\Component\Security\Core\User\User: plaintext
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre-… 7/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
Comme son nom l'indique, l'objet encodeur va encoder les mots de passe des utilisateurs. C'est
donc grâce à cette section que vous pourrez changer d'encodeur, c'est-à-dire la manière dont les
mots de passe sont encodés dans votre application.
Ici, nous utilisons plaintext qui laisse les mots de passe apparents (donc il n'encode rien en
fait !). Nous choisirons un encodeur plus sûr plus tard.
Les mots de passe sont visibles par la suite grâce à l'encodeur plaintext .
role_hierarchy
yaml
1 security:
2 role_hierarchy:
3 ROLE_ADMIN: ROLE_USER
4 ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
Comme nous l'avons vu, le "rôle" de l'utilisateur est central pour l'autorisation. Il est possible de
définir différents rôles et d'en attribuer un ou plusieurs pour un utilisateur donné. De même,
l'accès à chaque ressource est conditionné par un ou plusieurs rôles. Le contrôle d'accès s'assure
que l'utilisateur a le rôle nécessaire puis autorise (ou non) l'accès.
La hiérarchie des différents rôles est établie dans cette section. Par exemple, le rôle ROLE_USER
est inclus dans le rôle ROLE_ADMIN. Concrètement, cela veut dire qu'un utilisateur qui a le rôle
ROLE_ADMIN peut accéder à des pages qui nécessite seulement le rôle ROLE_USER.
Vous pouvez nommer vos rôles comme vous le souhaitez, l'important est qu'ils commencent par «
ROLE_ ».
Providers
yaml
1 security:
2 providers:
3 in_memory:
4 memory:
5 users:
6 user: { password: userpass, roles: [ 'ROLE_USER' ] }
7 admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
Si vous regardez le fichier, pour l'instant il n'y qu'un fournisseur et c'est in_memory (vous pouvez
tout à fait choisir un autre nom). C'est un fournisseur atypique utilisé pour le développement. En
effet, les utilisateurs, ici user et admin, sont répertoriés dans le fichier de configuration. Ainsi, nous
n'avons pas besoin d'une base de données pour tester la sécurité de notre application.
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre-… 8/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
Passée la phase de test, il faudra utiliser un autre type de fournisseur (par exemple un
fournisseur permettant de recourir à une base de données).
Firewalls
yaml
1 security:
2 firewalls:
3 dev:
4 pattern: ^/(_(profiler|wdt)|css|images|js)/
5 security: false
Le firewall permet de vérifier l'identité de l'utilisateur. Dans notre cas, notre firewall est dev
(ceux de démonstration ont été retirés). Il désactive la sécurité pour certaines URL. Nous y
reviendrons.
access_control
yaml
1 security:
2 access_control:
3 #- { path: ^/login, roles: ROLE_ADMIN }
Le contrôle d'accès vérifie que l'utilisateur a le(s) rôle(s) requis pour accéder au contenu demandé.
Les contrôles d'accès peuvent être utilisés :
à partir du fichier de configuration, comme c'est le cas ici. Pour cela, il faut appliquer règles
sur des URL. Par exemple, on peut sécuriser toutes les URL commençant par /admin ;
dans les contrôleurs directement. Pour cela, il faut appliquer des règles sur les méthodes
des contrôleurs. L'avantage est la grande liberté que cela apporte : les règles peuvent
changer en fonction des paramètres.
Après cette présentation du fichier de configuration, vous devez mieux comprendre ce qui peut
être configuré. Passons à l'étape suivante : l'authentification !
Pour cela, nous allons mettre en place un formulaire qui demande à l'utilisateur son adresse mail
et un mot de passe.
Créez un formulaire
C'est le plus simple, il s'agit d'intégrer un simple formulaire HTML : faisons-le en Twig, par
exemple.
twig
1 {% extends 'base.html.twig' %}
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre-… 9/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
2
3 {% block main %}
4 {% if error %}
5 <div class="alert alert-danger">
6 {{ error.messageKey|trans(error.messageData, 'security') }}
7 </div>
8 {% endif %}
9
10 <div class="row">
11 <div class="col-sm-5">
12 <div class="well">
13 <form action="{{ path('security_login') }}" method="post">
14 <fieldset>
15 <legend><i class="fa fa-lock" aria-hidden="true"></i> {{
'title.login'|trans }}</legend>
16 <div class="form-group">
17 <label for="username">{{ 'label.username'|trans }}</label>
18 <input type="text" id="username" name="username" value="{{
last_username }}" class="form-control"/>
19 </div>
20 <div class="form-group">
21 <label for="password">{{ 'label.password'|trans }}</label>
22 <input type="password" id="password" name="password" class="form-
control" />
23 </div>
24 <input type="hidden" name="_target_path" value="{{
app.request.get('redirect_to') }}"/>
25 <input type="hidden" name="_csrf_token" value="{{
csrf_token('authenticate') }}"/>
26 <button type="submit" class="btn btn-primary">
27 <i class="fa fa-sign-in" aria-hidden="true"></i> {{
'action.sign_in'|trans }}
28 </button>
29 </fieldset>
30 </form>
31 </div>
32 </div>
33 </div>
34 {% endblock %}
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre… 10/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
Formulaire de connexion
Créez un contrôleur
Pour manipuler un formulaire de connexion, il nous faut un contrôleur ! Ce contrôleur aura deux
fonctions : une pour la connexion et une pour la déconnexion.
php
1 <?php
2
3 namespace App\Controller;
4
5 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
6 use Symfony\Component\HttpFoundation\Response;
7 use Symfony\Component\Routing\Annotation\Route;
8 use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
9
10 class SecurityController extends AbstractController
11 {
12 /**
13 * @Route("/login", name="security_login")
14 */
15 public function login(AuthenticationUtils $authenticationUtils): Response
16 {
17 // retrouver une erreur d'authentification s'il y en a une
18 $error = $authenticationUtils->getLastAuthenticationError();
19 // retrouver le dernier identifiant de connexion utilisé
20 $lastUsername = $authenticationUtils->getLastUsername();
21
22 return $this->render('security/login.html.twig', [
23 'last_username' => $lastUsername,
24 'error' => $error,
25 ]
26 );
27 }
28
29 /**
30 * @Route("/logout", name="security_logout")
31 */
32 public function logout(): void
33 {
34 throw new \Exception('This should never be reached!');
35 }
36 }
37
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre… 11/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
l'authentification.
La fonction de déconnexion doit vous surprendre ! Nous avons dit qu'une action doit toujours
retourner une réponse : en fait, cette fonction ne sera jamais exécutée. Le composant Sécurité a
seulement besoin d'une URL pour effectuer la déconnexion.
Pour cela, nous allons créer une classe qui étend AbstractFormLoginAuthenticator du
composant Guard. Il faudra implémenter et compléter quelques fonctions :
1 <?php
2
3 namespace App\Security;
4
5 use App\Entity\User;
6 use Doctrine\ORM\EntityManagerInterface;
7 use Symfony\Component\HttpFoundation\RedirectResponse;
8 use Symfony\Component\HttpFoundation\Request;
9 use Symfony\Component\Routing\RouterInterface;
10 use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
11 use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
12 use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
13 use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
14 use Symfony\Component\Security\Core\Security;
15 use Symfony\Component\Security\Core\User\UserInterface;
16 use Symfony\Component\Security\Core\User\UserProviderInterface;
17 use Symfony\Component\Security\Csrf\CsrfToken;
18 use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
19 use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
20 use Symfony\Component\Security\Http\Util\TargetPathTrait;
21
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre… 12/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
78 {
79 return $this->passwordEncoder->isPasswordValid($user, $credentials['password']);
80 }
81
82 public function onAuthenticationSuccess(Request $request, TokenInterface $token,
$providerKey)
83 {
84 if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
85 return new RedirectResponse($targetPath);
86 }
87
88 return new RedirectResponse($this->router->generate('homepage'));
89 }
90
91 protected function getLoginUrl()
92 {
93 return $this->router->generate('security_login');
94 }
95 }
Une fois cette classe réalisée et correctement implémentée, passons à la création de notre classe
Utilisateur.
Une seule contrainte pour la création d'un utilisateur est d'implémenter l'interface UserInterface
du composant Security. Voici un exemple d'implémentation valide utilisé dans le projet de
démonstration :
php
1 <?php
2
3 namespace App\Entity;
4
5 use Doctrine\ORM\Mapping as ORM;
6 use Symfony\Component\Security\Core\User\UserInterface;
7 use Symfony\Component\Validator\Constraints as Assert;
8
9 /**
10 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
11 * @ORM\Table(name="blog_user")
12 *
13 */
14 class User implements UserInterface
15 {
16 /**
17 * @ORM\Id
18 * @ORM\GeneratedValue
19 * @ORM\Column(type="integer")
20 */
21 private $id;
22
23 /**
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre… 14/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
24 * @ORM\Column(type="string")
25 * @Assert\NotBlank()
26 */
27 private $fullName;
28
29 /**
30 * @ORM\Column(type="string", unique=true)
31 * @Assert\NotBlank()
32 * @Assert\Length(min=2, max=50)
33 */
34 private $username;
35
36 /**
37 * @ORM\Column(type="string", unique=true)
38 * @Assert\Email()
39 */
40 private $email;
41
42 /**
43 * @ORM\Column(type="string")
44 */
45 private $password;
46
47 /**
48 * @ORM\Column(type="json")
49 */
50 private $roles = [];
51
52 public function getId(): int
53 {
54 return $this->id;
55 }
56
57 public function setFullName(string $fullName): void
58 {
59 $this->fullName = $fullName;
60 }
61
62 public function getFullName(): string
63 {
64 return $this->fullName;
65 }
66
67 public function getUsername(): string
68 {
69 return $this->username;
70 }
71
72 public function setUsername(string $username): void
73 {
74 $this->username = $username;
75 }
76
77 public function getEmail(): string
78 {
79 return $this->email;
80 }
81
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre… 15/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
Il n'est pas obligatoire d'utiliser Doctrine ORM pour persister ses utilisateurs, comme nous
l'avons vu dans la section providers du fichier security.yaml.
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre… 16/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
1 # config/security.yaml
2
3 security:
4 encoders:
5 App\Entity\User: bcrypt
6
7 providers:
8 database_users:
9 entity: { class: App\Entity\User, property: username }
10
11 firewalls:
12 dev:
13 pattern: ^/(_(profiler|wdt)|css|images|js)/
14 security: false
15
16 main:
17 pattern: ^/
18 anonymous: true
19 logout:
20 path: security_logout
21 guard:
22 authenticators:
23 - App\Security\FormLoginAuthenticator
24
Et après tant d'efforts, et après avoir créé un utilisateur en base de données, vous pouvez
maintenant vous connecter :
L'utilisateur John est donc authentifié et aura les rôles définis pour cet utilisateur, que ce soit en
base de données, en mémoire, ou toute autre méthode que vous pouvez définir en créant votre
propre "User Provider", ou encore fournisseur d'utilisateurs.
Je suis un peu gêné de vous dire cela maintenant : vous pouvez générer ce code assez
facilement en installant l'extension MakerBundle et à l'aide des commandes make:user
et make:auth .
seulement !
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre… 17/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
1 <?php
2
3 class TestController extends AbstractController
4 {
5 public function index()
6 {
7 dump($this->getUser()->getUsername());
8 }
9 }
La fonction getUser() est disponible dans AbstractController et retourne soit nul, soit l'utilisateur
authentifié.
Si, pour une raison particulière, vous ne souhaitez pas utiliser cet alias, on peut injecter le service
Security dans l'action :
php
1 <?php
2
3 use Symfony\Component\Security\Core\Security;
4
5 class TestController extends AbstractController
6 {
7 public function index(Security $security)
8 {
9 dump($security->getUser());
10 }
11 }
Et vous pouvez réutiliser ce service pour retrouver l'utilisateur authentifié dans vos classes !
1 {{ app.user.username }}
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre… 18/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
Avec toutes ces informations, vous devriez être capable de développer une page "Compte
utilisateur" sans aucun souci !
Nous avons maintenant des utilisateurs qui peuvent s'authentifier et qui ont différents rôles.
L'idée d'un espace administrateur est de restreindre l'accès aux utilisateurs qui ont le rôle
ROLE_ADMIN .
1 <?php
2
3 namespace App\Controller\Admin;
4
5 use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
6 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
7 use Symfony\Component\Routing\Annotation\Route;
8
9 /**
10 * Controller used to manage blog contents in the backend.
11 *
12 * @Route("/admin/post")
13 * @IsGranted("ROLE_ADMIN")
14 */
15 class BlogController extends AbstractController
16 {
17 // ...
18 }
Une deuxième solution est d'utiliser un concept que vous avez déjà vu dans la première partie de
ce chapitre : définir une règle de contrôle d'accès.
Mettons à jour le fichier security.yaml et ajoutons une règle dans la section access_control :
yaml
1 access_control:
2 - { path: '^/admin', roles: ROLE_ADMIN }
Si vous essayez d'accéder à l'espace administration sans être connecté, le site redirigera
vers la page de connexion.
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre… 19/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
Je vois parfois, dans des applications, l'annotation @Security(), pourquoi tu n'en parles pas
?
Cette annotation est dépréciée et ne sera plus disponible dans Symfony 5 ! L'annotation
@IsGranted() a les mêmes fonctionnalités, donc vous pouvez convertir tous les appels à
l'annotation @Security() par @IsGranted().
On peut aussi affiner les différentes autorisations au niveau d'une action, d'un service ou même
d'un gabarit Twig.
1 {% if is_granted('ROLE_ADMIN') %}
2 <div class="section">
3 <a href="{{ path('admin_post_edit', {id: post.id}) }}">
4 <i class="fa fa-edit" aria-hidden="true"></i> {{ 'action.edit_post'|trans }}
5 </a>
6 </div>
7 {% endif %}
1 <?php
2
3 use Symfony\Component\Security\Core\Security;
4
5 class ExempleController extends AbstractController
6 {
7 public function index()
8 {
9 //...
10 if ($someConditions) {
11 $this->denyAccessUnlessGranted('ROLE_SPECIFIC');
12 }
13 }
14
15 // en utilisant l'injection de dépendances
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre… 20/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
D'accord, c'est très clair... mais j'ai un besoin un peu particulier ! Je veux par exemple
permettre à un utilisateur d'éditer un article s'il est le créateur de son article. Je ne vais pas
créer un rôle à chaque fois, si ?
Mais non, ne vous inquiétez pas ! Le contrôle de la sécurité en fonction d'un rôle, c'est le premier
niveau de permission implémenté par le composant Security. Le second niveau, c'est le contrôle
d'une action propre à un objet. Je vous explique.
1 <?php
2
3 use App\Entity\Article;
4 // ...
5
6 class ArticleController extends AbstractController
7 {
8 public function edit(Article $article)
9 {
10 if ($this->getUser() !== $article->getAuthor() || !$this->isGranted('ROLE_ADMIN')) {
11 throw $this->createAccessDeniedException();
12 }
13 }
14 }
Et ce code fonctionne parfaitement. Mais... nous avons de la logique business à réécrire dans le
contrôleur, dans les gabarits Twig, et si les règles changent ou si elles sont dynamiques, cela va
vite devenir compliqué à maintenir !
1 <?php
2
3 use App\Entity\Article;
4 // ...
5
6 class ArticleController extends AbstractController
7 {
8 public function edit(Article $article)
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre… 21/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
9 {
10 if (!$this->isGranted('EDIT', $article)) {
11 throw $this->createAccessDeniedException();
12 }
13 }
14 }
Pas tout à fait, nous allons devoir déplacer nos règles de décision métier dans une classe dédiée
appelée un Voteur.
Pour créer un Voteur, le plus simple est d'étendre la classe Voter du composant Security.
supports($attribute, $subject) : définit si le Voteur doit voter ou non sur cette demande
d'autorisation ;
voteOnAttribute($attribute, $subject, $token): cette fonction doit retourner true ou
false ; c'est ici que l'on peut décrire les conditions métiers qui conditionnent
l'autorisation.
Voici comment nous pourrions utiliser un Voter pour implémenter notre besoin :
php
1 <?php
2
3 namespace App\Security\Voter;
4
5 use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
6 use Symfony\Component\Security\Core\Authorization\Voter\Voter;
7 use Symfony\Component\Security\Core\User\UserInterface;
8 use Symfony\Component\Security\Core\Security;
9
10 class ArticleEditionVoter extends Voter
11 {
12 private $security;
13
14 public function __construct(Security $security)
15 {
16 $this->security = $security;
17 }
18
19 protected function supports($attribute, $subject)
20 {
21 return $attribute === 'EDIT'
22 && $subject instanceof App\Entity\Article;
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre… 22/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
23 }
24
25 protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
26 {
27 // on retrouve l'utilisateur (on peut aussi ré-utiliser $this->security)
28 $user = $token->getUser();
29
30 // si l'utilisateur n'est pas authentifié, c'est non!
31 if (!$user instanceof UserInterface) {
32 return false;
33 }
34
35 // l'utilisateur est l'auteur de l'article
36 if ($user === $subject->getAuthor()) {
37 return true;
38 }
39
40 // l'utilisateur est un administrateur
41 if ($this->security->isGranted('ROLE_ADMIN')) {
42 return true;
43 }
44
45 return false;
46 }
47 }
48
Dans ce Voteur, j'ai eu besoin de vérifier que l'utilisateur avait bien le rôle ROLE_ADMIN , j'ai donc
Ce Voteur est automatiquement configuré par Symfony, si vous n'avez pas désactivé
l’autoconfiguration, donc ce code est fonctionnel !
1 {% if is_granted('EDIT', post) %}
2 <div class="section">
3 <a href="{{ path('admin_post_edit', {id: post.id}) }}">
4 <i class="fa fa-edit" aria-hidden="true"></i> {{ 'action.edit_post'|trans }}
5 </a>
6 </div>
7 {% endif %}
Enfin, voici le code du contrôleur avec l'utilisation de l'annotation IsGranted() mise à jour :
php
1 <?php
2
3 use App\Entity\Article;
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre… 23/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
4 // ...
5
6 class ArticleController extends AbstractController
7 {
8 /**
9 * @IsGranted("EDIT", subject="article")
10 */
11 public function edit(Article $article)
12 {
13 // ...
14 }
15 }
Avec le système des Voteurs et la fonction isGranted(), vous pouvez donc contrôler l'accès aux
différentes actions de votre site, quelle que soit la complexité de vos règles métiers.
En résumé
Ça y est ! Grâce à ce chapitre, vous savez à présent mettre en place un espace membre pour votre
site. Vous êtes capable de construire un système d'authentification efficace qui garantit la
sécurité de votre application. De cette façon, vous pouvez restreindre l'accès à certaines pages en
exigeant des droits spécifiques à vos visiteurs pour l'afficher.
Mais vous pouvez aller beaucoup plus loin concernant la sécurité avec Symfony ! Si vous le
souhaitez, je vous invite à consulter la documentation officielle de Symfony. Vous pouvez aussi
utiliser la documentation de MakerBundle, le bundle communautaire, qui permet d'obtenir très
rapidement un espace utilisateur complet.
Vous pouvez définir des rôles pour les visiteurs pour établir des droits d'accès. Nous pouvons
contrôler les autorisations d'un utilisateur authentifié partout dans nos applications :
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre… 24/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
Dans la prochaine partie de ce cours, vous apprendrez comment développer une application de
qualité et la déployer en production.
À tout de suite !
Le professeur
Mickaël Andrieu
Consultant et Formateur Web / Data
OPENCLASSROOMS
OPPORTUNITÉS
AIDE
EN PLUS
Français
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre… 25/26
18/07/2022 07:16 Sécurisez l'accès de votre site web - Construisez un site web à l’aide du framework Symfony 5 - OpenClassrooms
https://openclassrooms.com/fr/courses/5489656-construisez-un-site-web-a-l-aide-du-framework-symfony-5/5654131-securisez-lacces-de-votre… 26/26