8791 sujets

Développement web côté serveur, CMS

Bonjour à tous!
J'ai une base de données mysql qui se comporte bizarrement : lors de l'inscription d'un nouveau membre, elle double les entrées Smiley sweatdrop (et maintenant, elle les triple même Smiley eek Smiley eek Smiley eek ...), alors qu'il n'y a qu'une seule requête.

Voici cette requête :

$req_inscr = "INSERT INTO users (id,pseudo,mdp,nom,prenom,mail,naissance) VALUES('','$pseudo','$mdp_ok','$nom','$prenom','$mail','$date_ok')" ;
		$res_inscr = mysql_query($req_inscr,$link); 


Je ne sais pas ce qui se passe, d'autant plus que je n'ai pas touché au code!

Dois-je faire appel à un exorciste?!?

Merci par avance de vos réponses.

EDIT : ah oui, petit détail très marrant, les différentes entrées ont chacune leur mot de passe! Un est correct, l'autre je ne sais pas d'où il vient et comme il est crypté, je ne peux même pas connaître sa provenance... Smiley decu Alors docteur? Smiley eek
Modifié par zamoy (13 Nov 2007 - 17:48)
Bon, j'ai réussi à stabiliser le nombre d'entrées à 2, puis je viens de réussir à le ramener à 1. Mais je ne sais pas comment... Smiley ohwell

Mais à priori, je ne suis pas une experte en php/mysql, mais à partir du moment où il n'y a qu'une seule requête 'INSERT' dans une page, il n'y a aucune raison que ça donne ça quand même? (je précise qu'il n'y a pas de boucle).

Est-ce que quelqu'un a déjà vu quelque chose de similaire? Et si oui, comment résoudre ça?
Jamais. Je n'ai jamais vu ce type d'erreur et c'est pourquoi je demandais la totalité de ton code. Mais à priori et à ma connaissance, il n'y a aucune raison pour qu'un INSERTsoit interprété plusieurs fois s'il n'y a pas de boucle ... Smiley confus
J'avais eu un truc similaire et il s'avère que c'était du à Firebug, je ne sais pas pour quel raison il chargeait deux fois ma page et faisait donc deux entrées dans la base de données.

Maintenant pour la triple entrée je ne sais pas si un autre plug-in fait la même chose Smiley smile

A+
zamoy a écrit :
Bon, j'ai réussi à stabiliser le nombre d'entrées à 2, puis je viens de réussir à le ramener à 1. Mais je ne sais pas comment... Smiley ohwell

Mais à priori, je ne suis pas une experte en php/mysql, mais à partir du moment où il n'y a qu'une seule requête 'INSERT' dans une page, il n'y a aucune raison que ça donne ça quand même? (je précise qu'il n'y a pas de boucle).

Est-ce que quelqu'un a déjà vu quelque chose de similaire? Et si oui, comment résoudre ça?


et si c'etait simplement un reload de la page ?
Aucun reload n'a été programmé!
Smiley eek
Et puis, je ne vois pas pourquoi le reload donnerait ça... Il y a un code destiné à contrôler que le pseudo n'existe pas déjà, donc en fait, le doublage se fait après ce code (sinon ça ne passerait pas), c'est à dire entre la page et la base...

C'est bien pour ça que c'est étrange!

Bon alors qui a une idée? Exorciste ou programmeur?
Salut,

je rejoins Gaylord.P : ce serait plus clair en voyant ton code Smiley cligne ! ( Formulaire + script PHP qui fait l'INSERT)...

A+
zamoy a écrit :
Aucun reload n'a été programmé!
Smiley eek

euh... ça je m'en doute...
zamoy a écrit :

Et puis, je ne vois pas pourquoi le reload donnerait ça... Il y a un code destiné à contrôler que le pseudo n'existe pas déjà, donc en fait, le doublage se fait après ce code (sinon ça ne passerait pas), c'est à dire entre la page et la base...

C'est bien pour ça que c'est étrange!

Bon alors qui a une idée? Exorciste ou programmeur?

Si il y a un bug le mieux en effet c'est de voir le code.
Bon, ok, puisque la demande est générale, voici le code :

Dernière page avant validation :

(récupération des données insérées dans les pages précédentes + choix du pseudo)

$prenom = $_GET['prenom']; 
$nom = $_GET['nom']; 
$mail = $_GET['mail']; 
$naissance	= $_GET['naissance']; 
		
	
$resultat = mysql_query("SELECT pseudo FROM `users` WHERE (pseudo = '$pseudo')"); 


switch (mysql_numrows($resultat))
{
case 0 :
	if (empty ($pseudo))
	{	echo 'Veuillez renseigner le champs pseudo<br /><br />';
		echo '<form action="inscription_v2.php?prenom='.$prenom.'&nom='.$nom.'&mail='.$mail.'&naissance='.$naissance.'&pseudo='.$pseudo.'" method="post">';
		echo '<fieldset><legend>Choix du pseudo</legend><br /><br />';
		echo '<label for="pseudo" class="alert">Champ "Pseudo" vide !</label><br />
		<input name="pseudo" id="pseudo" type="text" class="text" size="30" /><br /><br />';
			
		echo '<input class="submit" type="submit" name="submit_ins" id="submit_ins" value="continuer" />';

		echo '</fieldset>';
		echo '</form>'; 
		
		
		}
	else
	{	
	
		echo '<strong>'.$pseudo.'</strong>,<br />vous pouvez passer à l\'étape 3&nbsp;: 
		choix du mot de passe<br /><br />Le mot de passe que vous choisirez sera crypté pour plus de sécurité.';

		echo '<form action="inscription_v3.php?prenom='.$prenom.'&nom='.$nom.'&mail='.$mail.'&naissance='.$naissance.'&pseudo='.$pseudo.'" method="post" title="Formulaire d\'inscription.">
		<fieldset><legend>Choix du mot de passe</legend>
		<br /><br />

		<label for ="mdp1" class="label"><strong>Mot de passe
		</strong><img src="/imgs/asterix.gif" width="15" height="15"
		alt="Champ obligatoire." /></label><br />
		<input name="mdp1" id="mdp1" type="password" size="30" class="text" />
		<br />
		<br /><label for ="mdp2" class="label"><strong>Vérification du mot de passe
		</strong><img src="/imgs/asterix.gif" width="15" height="15" 
		alt="Champ obligatoire." /></label><br />
		<input name="mdp2" id="mdp2" type="password" size="30" class="text" />
		<br />
		<br />
		<br />
		<input  type="submit" name="submit_ins" id="submit_ins" value="continuer" class="submit"/>
		<br /></fieldset></form>'; }
break;

case 1 :
		echo 'le pseudo que vous souhaitez utiliser n\'est pas disponible, 
		veuillez en choisir un autre.<br /><br />';
		echo '<form action="inscription_v2.php?prenom='.$prenom.'&nom='.$nom.'&mail='.$mail.'&naissance='.$naissance.'&pseudo='.$pseudo.'"

		method="post" title="Formulaire d\'inscription.">
		<fieldset>
		<legend>Choix du pseudo</legend>
		<br /><br />

		<label for ="pseudo" class="label"><strong>Pseudo</strong>
		<img src="/imgs/asterix.gif" width="15" height="15" 
		alt="Champ obligatoire." /></label><br />
		<input name="pseudo" id="pseudo" type="text" size="30" class="text" />
		<br />
		<br />
		<br />
		<input  type="submit" name="submit_ins" id="submit_ins" value="continuer" class="submit"/>
		<br /></fieldset></form>';
break;}



Page de validation finale :

(récupération des données insérées dans les pages précédentes + choix du mot de passe)

if (empty($mdp1) OR empty($mdp2))
{
echo 'Vous ne pouvez pas laisser le mot de passe vide&nbsp;!';
echo '<form action="inscription_v3.php?prenom='.$prenom.'&nom='.$nom.'&mail='.$mail.'&naissance='.$naissance.'&pseudo='.$pseudo.'" method="post" title="Formulaire d\'inscription.">
		<fieldset><legend>Choix du mot de passe</legend>
		<br /><br />

		<label for ="mdp1" class="label"><strong>Mot de passe
		</strong><img src="<?echo $chemin;?/imgs/asterix.gif" width="15" height="15"
		alt="Champ obligatoire." /></label><br />
		<input name="mdp1" id="mdp1" type="password" size="30" class="text" />
		<br />
		<br /><label for ="mdp2" class="label"><strong>Vérification du mot de passe
		</strong><img src="/imgs/asterix.gif" width="15" height="15" 
		alt="Champ obligatoire." /></label><br />
		<input name="mdp2" id="mdp2" type="password" size="30" class="text" />
		<br />
		<br />
		<br />
		<input  type="submit" name="submit_ins" id="submit_ins" value="continuer" class="submit"/>
		<br /></fieldset></form>';
}

else
{

if 
($mdp1!==$mdp2)
		{echo '<strong>'.$pseudo.'</strong>,<br />Veuillez retaper le mot de passe et la vérification, car il y a eu une erreur lors de votre précédente saisie.<br /><br />';

		echo '<form action="inscription_v3.php?prenom='.$prenom.'&nom='.$nom.'&mail='.$mail.'&naissance='.$naissance.'&pseudo='.$pseudo.'" method="post" title="Formulaire d\'inscription.">
		<fieldset><legend>Choix du mot de passe</legend>
		<br /><br />

		<label for ="mdp1" class="label"><strong>Mot de passe
		</strong><img src="<?echo $chemin;?/imgs/asterix.gif" width="15" height="15"
		alt="Champ obligatoire." /></label><br />
		<input name="mdp1" id="mdp1" type="password" size="30" class="text" />
		<br />
		<br /><label for ="mdp2" class="label"><strong>Vérification du mot de passe
		</strong><img src="/imgs/asterix.gif" width="15" height="15" 
		alt="Champ obligatoire." /></label><br />
		<input name="mdp2" id="mdp2" type="password" size="30" class="text" />
		<br />
		<br />
		<br />
		<input  type="submit" name="submit_ins" id="submit_ins" value="continuer" class="submit"/>
		<br /></fieldset></form>';}



else
		{
		
$jour = substr ($_GET['naissance'], 0, 2);
$mois = substr ($_GET['naissance'], 3, 2);
$annee = substr ($_GET['naissance'], -4);


$array2 = array($annee, $mois, $jour);
$date_ok =  implode("-", $array2);

//echo $date_ok;

$mdp_ok = (sha1($mdp1));

		
		$req_inscr = "INSERT INTO users (id,pseudo,mdp,nom,prenom,mail,naissance) VALUES('','$pseudo','$mdp_ok','$nom','$prenom','$mail','$date_ok')" ;
		$res_inscr = mysql_query($req_inscr,$link); 
	mysql_free_result($res_inscr);

	
	if (!$res_inscr) 
{
   echo 'Impossible d\'exécuter la requête : '. mysql_error();
   exit;
}
	
	
mail (
''.$mail.'',
'XXXXXXXX.xxx : vos identifiants',
'
Pour vous connecter, vous aurez besoin de ces renseignements :

Pseudo : '.$pseudo.'
Mot de passe : '.$mdp1.'

',

'Sender: "XXXXX" <xxxx@xxxxx.xxx>'

);	
	
		
		
		echo 'Bravo, vous faites désormais partie des membres du site xxxxx.xxxx';
		
		echo '<br /><div class="pubctr"><a href="inserer_mm.php"><img src="imgs/pub/pub_inserer2.jpg" alt="xxx" width="400px" height="400px" /></a></div>';
		
		echo '<br />
<em>Conform&eacute;ment &agrave; l\'article&nbsp;34 de la Loi &quot;Informatique et Libert&eacute;s&quot; num&eacute;ro&nbsp;78-17 du 6&nbsp;janvier&nbsp;1978, vous disposez d\'un droit d\'acc&egrave;s, de modification, de rectification et de suppression des donn&eacute;es qui vous concernent.<br /> Vous pouvez l\'exercer en nous adressant une demande par le biais du <a href="contact.php">formulaire de contact</a>.</em>
<br /><br />
';		
}
}


(précision : lorsque la bdd insérait 2 voire 3 entrées à chaque inscription, il y avait aussi 2 ou 3 mails envoyés)

Toute suggestion ou remarque, même indépendante de la question en cours, est bienvenue, n'hésitez pas!
Salut zamoy Smiley cligne ,

quelques remarques générales :

* pourquoi avoir plusieurs pages plutôt qu'un seul formulaire ? D'autant que cela t'oblige à passer tes variables en GET et peut permettre à un petit plaisantin (si ! si ! il y a TOUJOURS un petit plaisantin Smiley lol ) de modifier les valeurs envoyées dans l'URL...

* pour des raisons de sécurité et plus généralement pour limiter les risques d'erreurs, c'est une bonne idée de toujours vérifier d'où proviennent les données. Par exemple, remplacer
$prenom = $_GET['prenom']; 
par
$prenom = (!empty($_GET['prenom'])) ? $_GET['prenom'] : ''; 

* le fait de ne pas bien différencier la provenance de tes variables t'amène visiblement à une mauvaise compréhension de comment ça fonctionne puisque l'action de tes form se termine par : ...&pseudo='.$pseudo.'" alors que la variable pseudo n'existera qu'après la soumission du formulaire et sera de type POST Smiley murf ... D'où la bonne idée, en passant, de rajouter
$pseudo = (!empty($_POST['pseudo'])) ? $_POST['pseudo'] : ''; 

* puisque désormais tu sais dès le début du script quand la variable pseudo est renseignée (= qu'elle existe et elle qu'elle n'est pas vide), tu peux éviter la requête de vérification "pseudo déjà utilisé" si elle est inutile.

* pour finir, je ne vois rien dans ton code qui soumette l'INSERT plusieurs fois, cela dit il suffit effectivement de faire F5 sur la dernière page pour que ce soit le cas. Une solution simple consiste à faire, juste après le mail(...) un header(Location: page_de_confirmation.php)

A+ Smiley smile
Pour t'assurer de ne pas faire une double entrée, tu peux d'abord tester s'il n'existe pas un enregistrement avec les mêmes caractéristiques, si c'est le cas, tu n'enregistres pas la demande.
Heyoan a 100% raison.

Juste au cas où tu ne serais pas habitué avec la syntaxe utilsée (opérateur ternaire - qui s'emploie ici parfaitement) je me permets de préciser que :
$prenom = (!empty($_GET['prenom'])) ? $_GET['prenom'] : ''; 

est identique à

if(!empty($_GET['prenom']))  $prenom = $_GET['prenom'];
else $prenom = '';


Sinon le coup du F5 aprés un submit c'est un grand classique Smiley cligne
Tout d'abord, un grand merci à vous pour ces pistes de réflexion.

Effectivement, quand je prends du recul, ce formulaire-là a quelques petites imperfections, j'ai déjà fait beaucoup mieux... Smiley confused

Pour la définition des variables, c'est vrai qu'il y a mieux... (j'utilise GET, POST ou ISSET en général avec un if/else)

Pour le passage en GET des éléments, j'ai bien conscience du problème que cela peut poser, mais si le petit plaisantin en question veut changer son nom et sa date de naissance entre temps, je ne vois pas où est le problème ! Il n'y a aucune vérification (de type comparaison avec une entrée de bdd, etc.) dans les données passées en GET, donc bon...

(le truc du pseudo passé en GET alors que c'est la page où il est défini, c'est une grosse erreur d'inattention et de copier-coller trop hatif, j'ai honte, je suis confuse Smiley confused Smiley confused !)

Le coup classique du F5 qui doublerait les entrées, j'y ai pensé... mais la vérification d'existance ou non permet d'éviter ça en principe...

Encore merci à vous! Smiley biggrin

Edit : et par rapport à mon problème de base, c'est que ce n'est pas un plaisantin qui s'est amusé à faire un F5 après validation, puisque c'est moi qui faisais des tests et qui ai pu constater de visu le doublage / triplage d'entrées... Smiley sweatdrop
Modifié par zamoy (22 Nov 2007 - 09:22)
Re-Salut zamoy,

même s'il est vrai que les données ne sont pas sensibles (à priori), je parlais de manière générale Smiley cligne ... D'autre part, que se passe-t-il si le PLAISANTIN en question ne fait pas que modifier les valeurs mais les remet à blanc, ou si l'email est invalide, ou s'il tente une injection SQL, ou si (etc, etc)... C'est toujours une bonne idée de vérifier les données reçues avant de les traiter Smiley vieux Smiley lol !

Sinon je ne voulais pas dire qu'il s'agissait d'un F5 inopportun mais seulement que je ne voyais rien dans ton code qui pouvait multiplier le traitement (la piste de Hacken est peut-être la bonne Smiley murf ), mais que dans tous les cas un header final protègerait du risque du F5...

A+ Smiley smile
Re-salut Heyoan,

Ah, le coup de l'injection sql, j'avoue, je ne connaissais pas! Smiley confus

Ok Grand Chef PHP, je promets désormais de toujours vérifier les données, j'ai bien compris la leçon! Smiley biggrin

L'air de rien, tu as vraiment raison d'insister là-dessus, car je suis toujours stressée par la sécurité, et du coup, ça me rend un grand service, je vais pouvoir progresser. Smiley biggthumpup

Encore merci à tous, c'est un vrai plaisir d'avoir un petit coup de main de votre part... Même si le sujet de départ reste toujours mystérieux Smiley help , j'aurai au moins appris des choses! Smiley biggrin