# Valider et filtrer les saisies en PHP avec filter_var

> Valider les saisies en PHP avec filter_var et filter_input_array : nombres, e-mail, URL, booléens, listes autorisées et limites. Avec exemples de code.

Source : https://phpsos.de/fr/blog/eingaben-validieren-php/  
État : 25/10/2026  
Fournisseur : PHP SOS, Assistance d'urgence PHP et sécurité des serveurs. Aide immédiate par WhatsApp : https://wa.me/491736494914?text=Bonjour%20PHP%20SOS%2C%20nous%20avons%20besoin%20d%27aide%20avec%20notre%20serveur%20PHP.%20Entreprise%20%3A%20%E2%80%A6%20Site%20web%20%3A%20%E2%80%A6

**En bref :** vous validez les saisies en PHP avec `filter_var()` ou `filter_input_array()` et des règles claires pour chaque champ : type, plage, longueur et valeurs autorisées. Ce qui ne correspond pas est rejeté, et non remanié en silence. La validation est importante pour des données propres et une surface d'attaque réduite, mais elle ne remplace ni les requêtes préparées contre l'injection SQL, ni l'encodage adapté au contexte contre XSS.

## Pourquoi « tout filtrer » n'est pas une stratégie

Dans de nombreux anciens projets PHP, on trouve au début de chaque fichier une boucle qui fait passer toutes les valeurs de `$_GET` et `$_POST` par une fonction de nettoyage. Cela donne une impression de sécurité. En pratique, elle supprime tantôt trop, par exemple les apostrophes dans les noms de famille, tantôt trop peu, car la même fonction doit valoir en même temps pour SQL, HTML et les noms de fichiers.

Une validation judicieuse procède autrement : elle demande, pour chaque champ, ce qui y est autorisé. Une quantité commandée est un entier compris entre 1 et une limite supérieure. Un champ de tri est l'une de trois valeurs fixes. Une date a un format précis et se situe après une autre date. Tout le reste est rejeté.

L'OWASP distingue deux niveaux : le contrôle **syntaxique**, qui vérifie qu'une valeur a la bonne forme, et le contrôle **sémantique**, qui vérifie qu'elle a du sens dans le contexte. Les deux relèvent du serveur ; les contrôles dans le navigateur ne servent qu'à la commodité d'usage.

## Les filtres fournis par PHP

L'extension Filter est incluse par défaut dans PHP. Les principaux filtres de validation selon le manuel PHP :

| Filtre | Vérifie | Options importantes et remarques |
|---|---|---|
| `FILTER_VALIDATE_INT` | entier | `min_range`, `max_range` |
| `FILTER_VALIDATE_FLOAT` | nombre décimal | `decimal` pour le séparateur |
| `FILTER_VALIDATE_BOOL` | valeur booléenne | avec `FILTER_NULL_ON_FAILURE`, distinguable de « faux » |
| `FILTER_VALIDATE_EMAIL` | forme d'une adresse e-mail | ne prouve pas que la boîte aux lettres existe |
| `FILTER_VALIDATE_URL` | forme d'une URL | vérifier soi-même le schéma, pas de domaines internationalisés |
| `FILTER_VALIDATE_IP` | adresse IP | indicateurs pour les plages privées et réservées |
| `FILTER_VALIDATE_REGEXP` | motif personnalisé | ancrer le motif avec `^` et `$` |

Le filtre de nettoyage `FILTER_SANITIZE_STRING` est obsolète depuis PHP 8.1. Si vous l'utilisez encore, migrez la validation vers des filtres adaptés et employez `htmlspecialchars()` pour l'affichage.

## filter_var en PHP : contrôler proprement un formulaire

Avec `filter_input_array()`, on peut contrôler un formulaire entier en une seule étape par rapport à une définition. Les champs inconnus ne sont pas repris :

```php
<?php
declare(strict_types=1);

$regeln = [
    'menge'   => ['filter' => FILTER_VALIDATE_INT,
                  'options' => ['min_range' => 1, 'max_range' => 50]],
    'email'   => FILTER_VALIDATE_EMAIL,
    'agb'     => ['filter' => FILTER_VALIDATE_BOOL, 'flags' => FILTER_NULL_ON_FAILURE],
    'versand' => ['filter' => FILTER_VALIDATE_REGEXP,
                  'options' => ['regexp' => '/^(standard|express)$/']],
];

$daten  = filter_input_array(INPUT_POST, $regeln) ?? [];
$fehler = [];

foreach ($regeln as $feld => $_) {
    if (!array_key_exists($feld, $daten) || $daten[$feld] === false || $daten[$feld] === null) {
        $fehler[] = $feld;
    }
}

if ($fehler !== []) {
    http_response_code(422);
    // afficher un message d'erreur par champ, ne pas traiter les saisies
}
```

Notez les comparaisons strictes avec `===` : une valeur valide `0` ou une chaîne vide ne doit pas être confondue avec un échec. Pourquoi les comparaisons lâches sont ici dangereuses est expliqué dans [Type juggling : les comparaisons lâches comme risque de sécurité](https://phpsos.de/fr/blog/type-juggling-php/). La façon dont PHP met à disposition les données de requête est décrite dans [Superglobales : $_GET, $_POST, $_FILES et autres](https://phpsos.de/fr/php/superglobals/).

## Pièges avec les e-mails, les URL et les textes libres

Certains filtres font moins que ce que leur nom laisse supposer :

1. **URL :** `FILTER_VALIDATE_URL` accepte aussi d'autres schémas que http et https. Vérifiez ensuite le schéma avec `parse_url()` par rapport à une liste fixe. Si l'URL est appelée par le serveur, des règles supplémentaires s'appliquent, voir [Empêcher le Server-Side Request Forgery en PHP](https://phpsos.de/fr/blog/ssrf-in-php/).
2. **Adresses e-mail :** le filtre vérifie la forme, pas la propriété. Qui a besoin d'être certain envoie un lien de confirmation.
3. **Texte libre :** noms, messages et adresses se laissent difficilement restreindre de façon pertinente à certains caractères. Contrôlez la longueur et l'encodage des caractères, par exemple avec `mb_check_encoding($wert, 'UTF-8')`, et fiez-vous à l'encodage à l'affichage.
4. **Expressions régulières :** sans `^` et `$`, un motif vérifie seulement s'il apparaît quelque part dans le texte, et non si la valeur entière correspond.
5. **Tableaux au lieu de chaînes :** un attaquant peut envoyer un tableau au lieu d'un texte. Sans contrôle de type, cela provoque des avertissements ou un comportement inattendu.

> **Astuce:**
> Pour des valeurs de sélection fixes comme le tri, la langue ou le mode d'expédition, une liste autorisée avec `in_array($wert, $erlaubt, true)` ou une expression `match` est plus simple et plus stricte que n'importe quelle expression régulière.

Une autre erreur fréquente concerne les nombres porteurs de sens, comme les prix, les quantités ou les remises. Qu'une valeur soit un nombre valide ne dit rien sur son autorisation dans le contexte. Une quantité négative, une remise supérieure à la valeur de la marchandise ou un prix repris du formulaire au lieu de la base de données sont des erreurs de logique classiques. Les prix, les autorisations et les valeurs d'état relèvent donc toujours du serveur, jamais de champs de formulaire cachés.

## JSON, webhooks et imports : la validation au-delà des formulaires

De nombreuses entrées ne sont plus aujourd'hui des formulaires, mais des requêtes JSON d'applications, des webhooks de services de paiement ou des fichiers d'import de fournisseurs. Là aussi : d'abord lire en toute sécurité, ensuite contrôler. L'OWASP conseille de limiter la taille et la profondeur d'imbrication avant même de lire les données. En PHP, `json_decode()` avec une profondeur maximale et `JSON_THROW_ON_ERROR` en assure une partie :

```php
<?php
$roh = file_get_contents('php://input', false, null, 0, 65536); // 64 Ko au maximum
try {
    $daten = json_decode($roh, true, 16, JSON_THROW_ON_ERROR);
} catch (JsonException) {
    http_response_code(400);
    exit;
}
if (!is_array($daten) || !is_string($daten['bestellnummer'] ?? null)) {
    http_response_code(422);
    exit;
}
```

Pour les webhooks, avant le contrôle du contenu se pose la question de savoir si le message provient réellement du service indiqué. Si le service propose une signature, vérifiez-la et comparez-la avec `hash_equals()`. Pour les fichiers d'import, contrôlez chaque ligne comme un formulaire et interrompez proprement en cas d'erreur, au lieu de reprendre des enregistrements à moitié valides.

Les messages d'erreur devraient nommer le champ concerné, mais ne pas renvoyer telle quelle la valeur rejetée. Sinon, le message d'erreur lui-même devient un nouveau point de sortie qu'il faudra encoder à nouveau.

## Ce que la validation ne peut pas faire

La validation réduit la surface d'attaque, mais, selon l'OWASP, elle n'est pas la défense principale contre l'injection. Un nom de famille avec apostrophe est valide et doit pourtant arriver sans danger dans une base de données. Cela n'est possible qu'avec des requêtes préparées, comme le montre le guide [Empêcher l'injection SQL en PHP](https://phpsos.de/fr/ratgeber/sql-injection-php/). Et un texte de commentaire valide ne devient inoffensif que par un encodage adapté au contexte à l'affichage.

Le bon ordre est donc : valider à la réception, paramétrer au traitement, encoder à l'affichage. S'y ajoutent des limites de taille en amont : le serveur web et PHP ne devraient même pas traiter entièrement des requêtes beaucoup trop volumineuses. Des réglages comme `post_max_size` y contribuent et devraient de toute façon être vérifiés après PHP2Shell.

## Comment PHP SOS aide-t-il concrètement ?

- Nous recensons toutes les entrées de votre application : formulaires, interfaces, téléversements, imports et webhooks.
- Nous définissons pour chaque champ ce qui est autorisé et remplaçons les fonctions de nettoyage généralisées par des contrôles clairs.
- Nous vérifions si les accès à la base de données et les sorties sont sécurisés indépendamment de la validation.
- Nous documentons les règles de façon que votre équipe puisse les poursuivre pour les nouvelles fonctions.

Une vérification systématique est décrite dans la prestation [audit de sécurité et test d'intrusion](https://phpsos.de/fr/leistungen/sicherheitsaudit-penetrationstest/).


## Questions fréquentes

**Quelle est la différence entre valider et nettoyer ?**  
Valider consiste à vérifier si une valeur correspond aux attentes et à la rejeter sinon. Nettoyer modifie la valeur, par exemple en supprimant des caractères. Pour les décisions de sécurité, rejeter est presque toujours préférable, car une valeur modifiée en silence peut engendrer de nouvelles erreurs.

**FILTER_SANITIZE_STRING est-il encore utilisable ?**  
Le filtre est marqué comme obsolète depuis PHP 8.1. Le manuel PHP recommande à la place htmlspecialchars() à l'affichage. Vous devriez migrer le code existant, car les fonctions obsolètes peuvent disparaître dans les versions futures.

**FILTER_VALIDATE_URL suffit-il à sécuriser les liens ?**  
Non. Le filtre ne vérifie que la forme de l'adresse. Selon le manuel, une URL valide ne doit pas nécessairement commencer par http ; vous devez donc contrôler vous-même le schéma par rapport à une liste autorisée comme https. Le filtre rejette les noms de domaine internationalisés.

**Dois-je aussi valider les données de ma propre base de données ?**  
À l'affichage, elles sont considérées comme non fiables et encodées en conséquence. Une nouvelle validation a du sens lorsque les données proviennent à l'origine de l'extérieur et sont désormais utilisées dans un nouveau contexte, par exemple comme nom de fichier ou partie d'une commande.

**La validation aide-t-elle contre PHP2Shell ?**  
Non. PHP2Shell concerne le traitement des requêtes dans l'interpréteur PHP, avant même que le code de votre application ne s'exécute. Seule la mise à jour de PHP, suivie du redémarrage de tous les processus PHP, y remédie.

## Sources

- [Manuel PHP : constantes de filtre](https://www.php.net/manual/de/filter.constants.php)
- [Aide-mémoire OWASP sur la validation des entrées (Input Validation Cheat Sheet)](https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html)
- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
