OVH Cloud OVH Cloud

Validation de formulaires enchaines

15 réponses
Avatar
Denis Bitouze
Bonjour,

je suis en train de me plonger dans PHP et suis sur le point de
finaliser un projet modeste pour lequel je me suis aidé du livre « PHP
& MySQL, Développement de sites Web » de Larry Ullman.

Mon problème est que, si je parviens sans problème à tester la
validité d'un formulaire côté serveur si le script « s'appelle
lui-même », je ne pas comment procéder si le script en appelle un
autre lorsque l'utilisateur appuie sur le bouton de type « submit
». Pour résumer, voici la structure de mon code :

<?php
// script script_php_1.php

if (isset($_POST['submit'])) { // Si le formulaire a été soumis

$message = NULL;

if ($_POST['champ1'] pas OK){
$champ1 = FALSE;
$message .= "<p>Le champ 1 ne va pas</p>";
}
else {
$champ1 = escape_data($_POST['champ1']);
}

if ($_POST['champ2'] pas OK){
$champ2 = FALSE;
$message .= "<p>Le champ 2 ne va pas</p>";
}
else {
$champ2 = escape_data($_POST['champ2']);
}

if ($message==NULL) { // Tout est OK
$_SESSION['champ1'] = $champ1;
$_SESSION['champ2'] = $champ2;
}
else { // L'un des deux champs au moins ne va pas
echo "$message";
}
}
?>

<!-- <form action="<?php $_SERVER['PHP_SELF']?>" method='post'> -->
<form action='script_php_2' method='post'>
Champ 1 : <input type='text' name='champ1' /> <br />
Champ 2 : <input type='text' name='champ2' /> <br />
<input type='submit' name='submit' value='OK' /><br />
</form>


Lorsque j'utilise :

<form action="<?php $_SERVER['PHP_SELF']?>" method='post'>

à la place de :

<form action='script_php_2' method='post'>

tout va bien mais, dans le cas contraire (celui du script ci-dessus),
l'utilisateur arrive au script script_php_2.php avec des champs champs
champ1 et
champ2 éventuellement non valides, sans qu'il en ait été empêché.

J'ai eu beau chercher dans les forums (où il y a pléthore de fils au
sujet de la validation de formulaires) et les divers tutoriaux du Web,
je n'ai rien trouvé lorsque, donc, le formulaire appelle un autre
script.

Merci d'avance pour toute indication.
--
Denis

5 réponses

1 2
Avatar
David JOURAND
Le Wed, 27 Sep 2006 13:03:00 +0000, Bruno Desthuilliers a écrit :

Pas besoin de POO ni de gros framework pour mettre en place une archi MVC
en PHP. Ca se gère aussi bien avec des scripts et des includes, sur le
même principe qu'évoqué dans le post de David ou le mien (voir aussi le
thread sur "les limites de PHP").


Entièrement d'accord, la référence aux framework MVC était plus pour
la compréhension de Denis.

--
David JOURAND - http://www.numabilis.com
Supprimer "site." et ".invalid" de mon adresse mail pour me répondre.

Avatar
Michel Billaud
Bruno Desthuilliers writes:

D'un autre côté, en mettant les données en session au fur et à mesure,
tu es sûr que ce sont bien les données validées, alors qu'avec des
champs cachés tu ne peux jamais être sûr (rien ne te dit que c'est bien
à partir de *ton* formulaire que la requête a été postée)... ce qui
pourrait t'amener à revalider toutes les données à chaque étape.


On peut transmettre des données "signées" (ou cryptées) dans les
champs cachés, ce qui permet de contrôler, au retour, que personne ne
les a bidouillées.

MB
--
Michel BILLAUD
LABRI-Université Bordeaux I tel 05 4000 6922 / 05 5684 5792
351, cours de la Libération http://www.labri.fr/~billaud
33405 Talence (FRANCE)

Avatar
Denis Bitouze
Le 02 oct 2006 à 18h43

On peut transmettre des données "signées" (ou cryptées) dans les
champs cachés, ce qui permet de contrôler, au retour, que personne ne
les a bidouillées.


Ah, ah ?! Et comment faire ?

Merci d'avance,
--
Denis

Avatar
Bruno Desthuilliers
Michel Billaud wrote:
Bruno Desthuilliers writes:

D'un autre côté, en mettant les données en session au fur et à mesure,
tu es sûr que ce sont bien les données validées, alors qu'avec des
champs cachés tu ne peux jamais être sûr (rien ne te dit que c'est bien
à partir de *ton* formulaire que la requête a été postée)... ce qui
pourrait t'amener à revalider toutes les données à chaque étape.


On peut transmettre des données "signées" (ou cryptées) dans les
champs cachés, ce qui permet de contrôler, au retour, que personne ne
les a bidouillées.


Heu... Ca revient à revalider les données d'une autre façon, non ?-)

Bon, ok, ça peut être - selon les cas - moins coûteux que de refaire la
validation initiale, mais bon... A ce stade, personnellement, j'arrête
de faire le puriste et je commence à utiliser les sessions.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in ''.split('@')])"


Avatar
Michel Billaud
Denis Bitouze writes:

Le 02 oct 2006 à 18h43

On peut transmettre des données "signées" (ou cryptées) dans les
champs cachés, ce qui permet de contrôler, au retour, que personne ne
les a bidouillées.


Ah, ah ?! Et comment faire ?


On suppose qu'on a déjà, par exemple, un nom client et un numéro de
tel (n'importe quoi) qu'on veut trimballer par le formulaire par champs
cachés.

[je fais cadeau des addslashes() et autres machins, pour la lisibilité.]

* fabrication du formulaire.

Dans le formulaire on met
<input type=hidden name='nomclient' value='$nomclient'>
<input type=hidden name='numerotel' value='$numerotel'>

Il faut que le serveur détienne une chaine de caractère secrète
($secret) connue de lui seul. Avec ça, il calcule une signature, en
combinant le secret et les données. Un md5() fait l'affaire.

$signature = md5 ( $nomclient . $numerotel . $secret );

signature qu'on fait passer aussi en champ caché

<input type=hidden name='signature' value='$signature'>

* récuperation des données

On suppose que les données arrivent par POST. Pour vérifier qu'elles
n'ont pas été bidouillées, on compare la signature re-calculée

$signature = md5 ( $_POST['nomclient'] . $_POST['numerotel'] . $secret );

avec celle qu'on a reçue du formulaire. Comme les attaquants ne
connaissent pas le secret, ils ne peuvent pas fabriquer une signature
correcte pour des données bidouillées.

if ($signature != $_POST['signature]) {
Header("Location: www.va-mourir.com");
exit;
}

**

Si pour d'autres raisons on ne souhaite pas que les données soient
transmises en clair, il faut plutot faire un cryptage. On construit
par exemple une chaine avec tout ce qu'on veut protéger

$clair = "$nomclient,$numerotel";

on la chiffre (doc PHP package mcrypt, j'ai pas vérifié)

$crypte = mcrypt_ecb(MCRYPT_TripleDES, $secret, $clair,
MCRYPT_ENCRYPT);

et on la balance en champ caché, qui nous revient normalement tel quel.

à la récupération, on déchiffre, et on explose pour récupérer les
champs. Si un attaquant bidouille le champ caché, le déchiffrement ne
marche pas puisque par hypothèse personne ne connait la clé utilisée
par le serveur pour chiffre/déchiffrer correctement.

MB

--
Michel BILLAUD
LABRI-Université Bordeaux I tel 05 4000 6922 / 05 5684 5792
351, cours de la Libération http://www.labri.fr/~billaud
33405 Talence (FRANCE)


1 2