Protection CSRF dans Symfony : le jeton des formulaires
La protection CSRF dans Symfony : un jeton placé dans chaque formulaire, qu'un autre site ne peut pas lire, pour refuser les requêtes forgées ailleurs.
// Le template envoie le jeton dans un champ caché : // <input type="hidden" name="_token" value="{{ csrf_token('supprimer-plat-' ~ plat.id) }}"> #[Route('/cuisine/plat/{slug:plat}/supprimer', methods: ['POST'])] public function supprimerPlat(Plat $plat, Request $request): Response { if (!$this->isCsrfTokenValid('supprimer-plat-'.$plat->getId(), $request->request->getString('_token'))) { throw new AccessDeniedHttpException('Jeton CSRF invalide.'); } // … }
Une requête forgée part du navigateur de la victime, avec ses cookies : sans autre indice, le serveur la prend pour une action légitime. Le jeton fait la différence. Le composant Form l'ajoute et le vérifie tout seul, dans un champ caché _token. Pour un formulaire écrit à la main, on le fabrique avec csrf_token() dans Twig et on le contrôle avec isCsrfTokenValid() dans le contrôleur, comme ci-dessus. Les pièges classiques : un identifiant de jeton qui diffère entre le template et le contrôleur, et chaque envoi est refusé ; une suppression déclenchée par un simple lien en GET, qu'aucun jeton ne protège.
Les exercices passent du formulaire généré par le composant Form à un formulaire POST écrit à la main pour retirer un plat de la carte, avec un jeton propre à chaque plat, puis à un formulaire maudit dont le jeton ne correspond plus.
3 exercices font travailler cette notion, en écrivant du code dans le navigateur.
Dans les parcours
- Un formulaire digne de ce nom Symfony pour les devs PHP · chapitre 3 : Les parchemins de la taverne
- Retirer un plat Symfony pour les devs PHP · chapitre 3 : Les parchemins de la taverne
- 🐉 Boss : le parchemin maudit Symfony pour les devs PHP · chapitre 3 : Les parchemins de la taverne