Le problème des données utilisateurs
Il n’y a qu’une règle que vous devez absolument retenir concernant les formulaires HTML : il ne faut jamais faire confiance aux données envoyées par les utilisateurs.
En effet, vous ne devez jamais vous attendre à ce que vos formulaires soient correctement remplis : certains utilisateurs vont faire des fautes d’inattention ou vont avoir la flemme de remplir tous les champs de votre formulaire tandis que d’autres, malveillants, vont essayer d’exploiter les failles de votre formulaire pour récupérer des données dans votre base de données ou pour tromper vos utilisateurs.
Les mécanismes d’intrusion et de protection des formulaires sont relativement complexes pour quelqu’un qui n’a pas une vue d’ensemble sur les langages utilisés mais je vais essayer d’illustrer le problème et les solutions possibles le plus simplement possible.
Reprenons le formulaire créé à la partie précédente par exemple. Rien n’empêche un utilisateur, dans ce formulaire, d’envoyer des valeurs aberrantes comme 2000 ans pour son âge ou des données de type invalide comme des éléments HTML à la place de son nom ou encore de renvoyer le formulaire à moitié ou complètement vide.
Dans ces cas-là, les données reçues vont être inexploitables et ce n’est pas ce que nous voulons.
De plus, ici, rien n’empêcherait un utilisateur malveillant d’injecter du code JavaScript dans notre formulaire pour ensuite essayer de tromper des utilisateurs ou encore pour tenter d’injecter le code malveillant dans notre base de données.
Nous n’allons pas entrer dans les détails ici car c’est assez complexe et car vous ne pourrez pas comprendre sans connaitre le JavaScript mais grosso modo retenez qu’ici un utilisateur peut tout à fait envoyer du code dans vos champs de formulaire et que le code envoyé risque d’être exécuté à un moment ou à un autre de notre côté.
Quelles solutions pour sécuriser nos formulaires ?
Ici, il va falloir faire la différence entre deux types d’utilisateurs qui vont être gérés de façons différentes : les utilisateurs maladroits qui vont envoyer des données invalides par mégarde et les utilisateurs malveillants qui vont tenter d’exploiter des failles de sécurité dans nos formulaires pour par exemple récupérer les données personnelles d’autres utilisateurs.
Pour ce premier groupe d’utilisateurs qui ne sont pas mal intentionnés, la première action que nous allons pouvoir prendre va être d’ajouter des contraintes directement dans notre formulaire pour limiter les données qui vont pouvoir être envoyées.
Pour cela, nous allons pouvoir utiliser des attributs HTML comme required
, min
et max
que nous allons étudier dans la suite de la leçon et allons devoir faire le maximum pour préciser les bonnes valeurs dans l’attribut type
de l’élément input
à chaque fois.
Nous allons ensuite également pouvoir tester que les données nous conviennent dès le remplissage d’un champ ou au moment de l’envoi du formulaire grâce au HTML ou au JavaScript (principalement) et bloquer l’envoi du formulaire si des données ne correspondent pas à ce qu’on attend.
Tout cela ne va malheureusement pas être suffisant contre les utilisateurs malintentionnés pour la simple et bonne raison que n’importe qui peut neutraliser toutes les formes de vérification effectuées dans le navigateur.
Pour cela, il suffit par exemple de désactiver l’usage du JavaScript dans le navigateur et d’inspecter le formulaire pour supprimer les attributs limitatifs avant l’envoi.
Contre les utilisateurs malveillants, nous allons donc également devoir vérifier les données après l’envoi du formulaire et neutraliser les données potentiellement dangereuses. Nous allons effectuer ces vérifications en PHP, côté serveur.
Ces deux niveaux de vérifications (dans le navigateur / côté serveur) doivent être implémentés lors de la création de formulaires. En effet, n’utiliser qu’une validation dans le navigateur laisse de sérieuses failles de sécurité dans notre formulaire puisque les utilisateurs malveillants peuvent désactiver ces vérifications.
N’effectuer qu’une série de vérifications côté serveur, d’autre part, serait également une très mauvaise idée d’un point de vue expérience utilisateur puisque ces vérifications sont effectuées une fois le formulaire envoyé.
Ainsi, que faire si des données aberrantes mais pas dangereuses ont été envoyées par un utilisateur maladroit ? Supprimer les données ? Le recontacter pour qu’il soumette à nouveau le formulaire ? Il est bien plus facile dans ce cas de vérifier directement les données lorsqu’elles sont saisies dans le navigateur et de lui faire savoir si une donnée ne nous convient pas.
Vérification et validation des données de formulaire dans le navigateur
Les processus de validation des données que nous allons pouvoir mettre en place dans le navigateur vont s’effectuer avant ou au moment de la tentative d’envoi du formulaire.
L’objectif va être ici de bloquer l’envoi du formulaire si certains champs ne sont pas correctement remplis et de demander aux utilisateurs de remplir correctement les champs invalides.
Une nouvelle fois, cette série de validations va s’adresser aux utilisateurs étourdis / flemmards mais ne va pas bloquer les utilisateurs malveillants car n’importe quel utilisateur peut supprimer à la main des parties de code HTML en inspectant le code de la page et désactiver le JavaScript dans son navigateur.
La première chose à faire ici va déjà être de s’assurer qu’on a bien précisé les bons types d’input
pour chaque champ de formulaire car la plupart des navigateurs récents proposent des systèmes de contrôle.
Par exemple, les navigateurs bloquent aujourd’hui l’envoi de code JavaScript et empêchent l’envoi du formulaire selon que certaines données ne soient pas de la forme attendue.
Essayez par exemple de rentrer un prénom dans le champ de formulaire demandant un email : votre navigateur devrait renvoyer une erreur et vous demander d’ajouter un signe @
dans vos données.
En plus de ces vérifications faites par le navigateur, le HTML propose aujourd’hui des options de validation relativement puissantes. La validation des données en HTML va principalement passer par l’ajout d’attributs dans les éléments de formulaire. Nous allons ainsi pouvoir utiliser les attributs suivants :
Attribut | Définition |
---|---|
size | Permet de spécifier le nombre de caractères dans un champ |
minlength | Permet de spécifier le nombre minimum de caractères dans un champ |
maxlength | Permet de spécifier le nombre maximum de caractères dans un champ |
min | Permet de spécifier une valeur minimale pour un champ de type number ou date |
max | Permet de spécifier une valeur maximale pour un champ de type number ou date |
step | Permet de définir un multiple de validité pour un champ acceptant des donnés de type nombre ou date. En indiquant step="4" , les nombres valides seront -8, -4, 0, 4, 8, etc. |
autocomplete | Permet d’activer l’auto complétion pour un champ : si un utilisateur a déjà rempli un formulaire, des valeurs lui seront proposées automatiquement lorsqu’il va commencer à remplir le champ |
required | Permet de forcer le remplissage d’un champ. Le formulaire ne pourra pas être envoyé si le champ est vide |
pattern | Permet de préciser une expression régulière. La valeur du champ devra respecter la contrainte de la regex pour être valide |
Note : les expressions régulières constituent un langage à part. Elles vont consister en la création de « motifs » ou de chaine de caractères constituées de caractères à la signification spéciale et qui vont servir à décrire un ensemble de chaines de caractères possibles. Les expressions régulières sont utilisées conjointement avec de nombreux langages informatiques pour comparer des données envoyées avec le motif attendu et les refuser si elles ne correspondent pas. Bien évidemment, l’objet de cette leçon n’est pas de faire un cours sur les expressions régulières.
Reprenons notre formulaire précédent en se concentrant sur certains champs en particulier et ajoutons quelques contraintes sur les données que l’on souhaite recevoir :
- Les nom, prénom, adresse mail et mot de passe sont désormais obligatoires
- Les nom et prénom doivent faire au moins 2 caractères et maximum 25 caractères ;
- L’âge doit être compris entre 16 et 99 ans ;
- La description de l’expérience professionnelle ne doit pas excéder 500 caractères ;
- Le mot de passe doit contenir au moins 8 caractères.
See the Pen Cours HTML CSS 11.3.1 by Pierre (@pierregiraud) on CodePen.
Essayez d’envoyer le formulaire ci-dessus en remplissant mal les différents champs : le navigateur va vous indiquer les différentes erreurs et va bloquer l’envoi du formulaire tant que vous ne les aurez pas corrigées.
Vous pouvez noter que l’attribut required
possède une valeur muette : il n’est pas nécessaire de la fournir (car elle est unique) et il suffit donc de préciser le nom de l’attribut pour rendre le remplissage du champ obligatoire.