← Symfony 8.0 — architecture et préparation certification

Module 4 / 8 · 90 min

Formulaires, contraintes et CSRF

Valider un modèle d’entrée avant de déclencher le métier.

Votre progression apparaîtra ici lorsque JavaScript est actif.

La progression et le meilleur score sont enregistrés uniquement dans ce navigateur. Aucun compte n’est nécessaire ; effacer les données du navigateur les supprime. Les durées de modules sont indicatives et incluent les exercices.

Comprendre le mécanisme

Le composant Form transforme une soumission en données structurées. handleRequest prend en compte la requête ; isSubmitted et isValid répondent à des questions différentes. Un type de formulaire décrit les champs et leurs options. Les contraintes du Validator contrôlent les valeurs et groupes de validation. Une transformation convertit une représentation sans remplacer la validation du domaine obtenu.

Raisonner et vérifier

Un jeton CSRF protège le déclenchement d’une action dans un contexte de navigateur. Il n’authentifie pas une personne et n’autorise pas une ressource. Les uploads exigent aussi contrôle de contenu et destination. Pour une opération sensible, mappez le formulaire à un DTO dédié puis appelez le service métier seulement après validation et autorisation. Conservez les messages d’erreur utiles et testez les soumissions partielles ou mal formées.

Soumission et conformité sont deux états

Un formulaire peut avoir reçu une demande sans être conforme. isSubmitted et isValid répondent donc à des questions différentes. La persistance doit suivre le contrat prévu après ces vérifications, pas seulement le fait qu’un bouton a été activé. Les tests doivent envoyer une donnée invalide et contrôler l’absence d’écriture, même si le formulaire contient déjà un objet ou des valeurs récupérables par getData.

Erreur fréquente à comprendre

isSubmitted implique nécessairement isValid.

Soumission et conformité sont des états distincts.

Exprimer les invariants au bon niveau

Une contrainte de propriété peut vérifier un champ ; une cohérence entre deux champs d’un DTO peut demander une validation au niveau de la classe. Par exemple, une date de fin doit être comparée à la date de début selon le sens du parcours. Cette validation de données ne prouve pas que l’acteur a le droit de modifier l’objet. Maintenez une décision d’autorisation distincte avant l’effet.

Erreur fréquente à comprendre

Une contrainte remplace toute permission sur l’objet.

Le droit métier est une décision distincte.

Le jeton CSRF dépend du contexte

Un champ nommé token ne constitue pas une preuve si le serveur ne le vérifie pas selon l’usage et la session attendus. Le contrôle cible une demande forgée pouvant profiter de l’identité automatique du navigateur. Il ne remplace pas un voter sur une ressource. Testez valeur absente, incorrecte et valide, puis vérifiez séparément ce qu’un acteur connecté mais non autorisé peut encore demander.

Erreur fréquente à comprendre

Un champ nommé token valide automatiquement la demande.

La valeur doit être vérifiée selon son usage.

Limiter un fichier selon son usage

Une extension ou un Content-Type client ne suffit pas à établir le format, la sécurité ou le coût d’un fichier. Définissez taille, contenu accepté et traitement, puis gardez les limites amont et serveur cohérentes. Le stockage et la restitution doivent aussi éviter des chemins ou exécutions non maîtrisés. Un refus doit être testé sans laisser une importation partielle non prévue par le contrat.

Erreur fréquente à comprendre

Le suffixe du nom client garantit un upload sain.

La déclaration doit être confrontée au contenu et au contrat.

Transformer n’est pas valider tout le domaine

Un DataTransformer peut convertir une représentation en une autre et signaler un échec de conversion. Il ne garantit pas toutes les règles métier de l’objet obtenu. Une valeur convertie en nombre peut encore dépasser une borne ou être interdite dans l’état actuel. Distinguez grammaire d’entrée, représentation technique et invariants afin que chaque échec ait une responsabilité et un test explicites.

Erreur fréquente à comprendre

Toute chaîne reçue se transforme sans erreur en objet métier.

Les formats et valeurs peuvent être incompatibles.

Choisir les groupes selon le parcours

Les groupes de validation déterminent quelles contraintes s’appliquent à une situation. Un brouillon et une publication complète peuvent avoir des exigences différentes, mais cette flexibilité doit rester contrôlée. Vérifiez la sélection effective et les chemins qui pourraient contourner un groupe nécessaire. Un test nominal d’une seule étape ne prouve pas qu’un appel direct à une autre étape respecte les mêmes préconditions.

Erreur fréquente à comprendre

Tout groupe couvre automatiquement toutes les étapes métier.

Le choix de groupe détermine les contraintes actives.

Ne pas confondre visibilité de champ et admission

Un client peut construire sa propre demande et envoyer des valeurs absentes de l’interface affichée. Le serveur doit donc maîtriser les champs admis et l’usage qu’il en fait. Masquer un input ne protège pas une propriété sensible contre toute écriture réseau. Les tests doivent inclure des champs inattendus et vérifier que le modèle ne gagne pas un privilège ou un état impossible.

Erreur fréquente à comprendre

Masquer un input interdit toute modification réseau.

L’interface ne limite pas un client direct.

Contrôler le mapping des données

Le mapping du formulaire doit préserver les responsabilités et invariants de l’objet cible. Évitez de donner à une entrée libre l’accès à toutes les propriétés d’une entité, notamment rôles et propriétaire. Un DTO peut limiter ce contrat puis être traduit en opération métier autorisée. Le fait qu’un champ existe dans l’objet ne suffit pas à justifier qu’il soit modifiable dans ce parcours.

Erreur fréquente à comprendre

Tout nom reçu doit modifier librement toute propriété.

Le mapping doit préserver les invariants et droits.

Une erreur utile sans divulgation

Le message de validation doit aider à corriger l’entrée sans exposer de secret ou une trace interne. Les noms de propriétés techniques et valeurs sensibles peuvent demander une représentation publique différente. Conservez les diagnostics nécessaires dans un périmètre privé. Testez aussi les erreurs de transformation et exceptions inattendues : ces chemins ne doivent pas contourner la politique de présentation appliquée aux violations ordinaires.

Erreur fréquente à comprendre

Une violation doit afficher toutes les valeurs sensibles du compte.

Le diagnostic doit être minimisé.

Vérifier le refus et le non-effet

Une erreur affichée après une écriture ne fournit pas la propriété d’un rejet avant traitement. Pour chaque classe invalide, vérifiez réponse, état du stockage et appels aval pertinents. Gardez un cas valide qui confirme que le formulaire peut réellement aboutir. Cette matrice rend visibles les responsabilités séparées de soumission, conversion, validation, CSRF et autorisation, au lieu de les résumer au seul état visuel du bouton.

Erreur fréquente à comprendre

Un formulaire vert suffit à prouver tous les refus.

Les chemins négatifs vérifient la frontière.

Atelier guidé : lire, expliquer et vérifier le code

// Extrait après handleRequest($request) :
if ($form->isSubmitted()) {
    $repository->save($form->getData());
}

L’extrait de l’atelier utilise seulement isSubmitted avant de récupérer les données et de demander leur persistance. Il peut donc ignorer des violations présentes sur un formulaire effectivement soumis. getData n’est pas une preuve générale de conformité et le nom save ne promet ni validation CSRF ni autorisation sur l’objet.

Construisez une demande de laboratoire avec un champ invalide puis observez l’appel au repository au moyen d’un double de test. La version correcte doit empêcher cet appel et présenter l’erreur prévue. Ajoutez ensuite un cas de cohérence entre deux champs et un acteur interdit sur l’objet. Vous vérifierez ainsi plusieurs frontières indépendantes, plutôt que donner au seul signal de soumission la responsabilité de toutes les règles du parcours.

Exemple commenté

<?php
// Fragment dans un contrôleur disposant de $form et $request.
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
    $command = $form->getData();
    // Autoriser puis transmettre la commande au service applicatif.
}

La condition évite d’exécuter le métier lors du premier affichage ou d’une soumission invalide. La décision d’autorisation reste explicite.

Exercice de mise en pratique

Créez un DTO de réservation avec quantité positive, email valide et une contrainte entre deux dates.

Voir une proposition de correction

Associez les contraintes simples aux champs et une validation de cohérence au DTO. Testez formulaire non soumis, données invalides, jeton absent et chemin autorisé.

Points de vérification

  • Séparer transformation et validation.
  • Contrôler soumission et validité.
  • Tester CSRF indépendamment des rôles.

Contrôle de connaissances

Cours associé : Formulaires, contraintes et CSRF ↗
Quelle condition doit précéder le traitement d’un formulaire web valide ?

Documentation de référence ↗

Validation du module

101 questions, objectif pédagogique de 75 %. Durée conseillée de 150 minutes, sans limite imposée. Les questions et les choix sont mélangés ; le corrigé apparaît après validation. Le contrôle rapide de la leçon et l’examen final du cours restent des exercices distincts.

Commencer ou reprendre les 101 questions →