HOWTO · PHP
Nettoyer les entrées en PHP
Dans l'article d'aujourd'hui, nous allons apprendre à nettoyer les données d'entrée en PHP avant de les transmettre à la base de données.
Sur cette page
Aucune étape universelle ne rend sûre toute valeur non fiable. Déterminez ce que représente la valeur, vérifiez qu’elle respecte les exigences correspondantes, ne la normalisez que si l’application suit une règle claire, encodez-la pour le contexte où elle sera affichée et utilisez des requêtes paramétrées pour la transmettre à une base de données. Ces opérations répondent à des besoins différents : la validation accepte ou rejette une valeur, l’assainissement la transforme et l’encodage de sortie représente les caractères de manière sûre dans un contexte précis. Aucune ne garantit à elle seule l’intégrité des données ni ne protège toutes les utilisations d’une valeur.
Ce que l’assainissement des entrées PHP peut et ne peut pas faire
Le traitement des entrées commence par les règles propres au champ. Un âge, une adresse e-mail, un nom d’affichage et un terme de recherche n’ont pas les mêmes formes valides. La validation vérifie qu’une valeur respecte ces règles ; la normalisation applique une transformation intentionnelle et documentée, comme la suppression des espaces en début et en fin de chaîne. Un assainisseur peut supprimer ou transformer des caractères, mais cela risque de modifier silencieusement la saisie de l’utilisateur sans pour autant rendre le résultat adapté à tous les usages ultérieurs.
Si l’application doit conserver la valeur d’origine, gardez-la séparée de ses représentations normalisées ou encodées. Ne supprimez pas des caractères uniquement parce qu’ils semblent inhabituels : les noms et d’autres textes légitimes peuvent contenir des signes de ponctuation ou des caractères non ASCII. Choisissez aussi le traitement en fonction de l’usage. Une sortie HTML nécessite un encodage HTML, tandis que les valeurs SQL doivent être transmises comme paramètres. Ces protections ne sont pas interchangeables.
Échapper le HTML lors de l’affichage des entrées utilisateur
Encodez le texte lorsque vous l’insérez dans un nœud de texte HTML ou dans un attribut entre guillemets. Pour une sortie HTML courante, htmlspecialchars() convertit les caractères ayant une signification en HTML, notamment les esperluettes, les chevrons et les guillemets lorsque les indicateurs appropriés sont utilisés. htmlentities() encode également les caractères qui possèdent des entités HTML nommées. Aucune de ces fonctions n’est un assainisseur HTML à usage général : encoder une valeur pour un nœud de texte ne permet pas de l’insérer sans risque dans du JavaScript, du CSS, une URL ou du balisage HTML brut. Utilisez l’encodeur et les règles adaptés au contexte de sortie précis.
Cet exemple autonome encode un nom pour un nœud de texte HTML. Le nom affiché dans le bloc immuable reste en anglais :
<?php
$name = 'Ada & Sam';
echo htmlspecialchars($name, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), PHP_EOL;
Ada & Sam
Les éléments d’exécution fournis confirment cette sortie. Il s’agit d’une chaîne destinée à un contexte de texte HTML, et non d’une valeur à réutiliser en SQL ou en JavaScript.
Valider et normaliser les entrées avec filter_var()
filter_var() applique une opération de validation ou de filtrage choisie ; ce n’est pas un assainisseur HTML. Par exemple, filter_var($email, FILTER_VALIDATE_EMAIL) renvoie l’adresse e-mail acceptée, ou false si elle ne correspond pas au filtre. filter_var($count, FILTER_VALIDATE_INT) peut valider un entier ; des options permettent de préciser une plage lorsque l’application en a besoin. Vérifiez explicitement la valeur de retour, car false signale un échec de validation.
Les filtres d’assainissement peuvent transformer les données au lieu de prouver qu’elles sont valides. Par exemple, FILTER_SANITIZE_EMAIL supprime les caractères que ce filtre n’autorise pas ; il ne confirme pas que l’adresse obtenue appartient à un utilisateur ni qu’elle peut recevoir du courrier. Si l’application choisit de normaliser une entrée, définissez la règle, puis validez le résultat. Évitez de vous fier à FILTER_SANITIZE_STRING comme solution générale : supprimer le balisage ne fournit pas un encodage de sortie adapté au contexte et ne rend pas sûr un contenu arbitraire.
Utiliser des requêtes préparées pour SQL
Utilisez des requêtes paramétrées pour séparer la syntaxe SQL des valeurs fournies par l’utilisateur. Avec PDO, préparez une requête contenant un paramètre fictif, puis transmettez la valeur séparément lors de l’exécution. Par exemple, le modèle consiste à écrire $statement = $pdo->prepare('SELECT id, email FROM Users WHERE lastname = :lastname');, puis $statement->execute(['lastname' => $lastname]);. Il s’agit d’un fragment illustratif : $pdo doit déjà être connecté à la base de données visée ; le service de base de données et son schéma ne sont pas détaillés dans cet exemple.
PDO n’assainit pas les données arbitraires. Pour les valeurs de la requête, la liaison des paramètres protège contre l’injection SQL ; elle ne vérifie pas qu’une valeur est pertinente pour l’application. Validez les valeurs selon les règles propres à leurs champs. Pour les identifiants tels que les noms de tables ou de colonnes, qui ne peuvent généralement pas être transmis comme paramètres de valeur, utilisez une autre méthode de construction de requête. MySQLi prend également en charge les requêtes préparées ; utilisez son API de liaison des paramètres avec cette interface.
Traiter les champs de profil selon leur type attendu
Appliquez une règle distincte à chaque champ de profil. Validez une adresse e-mail et, si nécessaire, confirmez-en la propriété au moyen d’un parcours applicatif ; ne supprimez les espaces d’un nom d’affichage que si c’est la règle prévue ; validez un code postal selon la région concernée au lieu de supposer qu’il existe un format universel. Pour un champ numérique, analysez la valeur et vérifiez la plage autorisée avant de l’utiliser. Conservez les signes de ponctuation et les caractères Unicode légitimes lorsque le champ les autorise.
Lorsque vous affichez sur une page des valeurs de profil enregistrées, encodez-les au moment de la sortie selon le contexte HTML précis, même si elles ont été validées lors de leur saisie. Pour rechercher un profil, transmettez les valeurs à l’aide de requêtes préparées. En traitant séparément la validation, la normalisation, le paramétrage des requêtes et l’encodage de sortie, vous pouvez mieux raisonner sur chaque étape et éviter de prendre une transformation pour une protection universelle.