Controle anti-spam d'un formulaire

Eléphant du PHP | 227 Messages

11 févr. 2006, 15:53

Bonjour à tous,

J'aurai pu continuer cette demande sur mon dernier post, mais j'ai préféré reformuler.

J'ai suite à l'explication et l'aide de Cyrano (code que je reprend ici), rajouter un formulaire très simple en vu de test, de la façon suivante, cela pour que les robots ne puissent validé un formulaire automatiquement.
<?php
session_start();
$chiffre = rand(120000,600000); // Chiffre aléatoire
$_SESSION['chiffre'] = $chiffre; // Mise en session du chiffre
echo("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" xml:lang="fr" />
<title>Affichage d'une image générée</title>
<meta http-equiv="Content-type" content="image/png" />
</head>
<body>
<form method="post" action="" />
<img src="./captcha.php" alt="" /> &nbsp;&nbsp;
<input type="text" name="item" />
<input type="hidden" name="chif" value="<?php echo $_SESSION['chiffre'] ?>" />
<input type="submit" name="ok" />
</form>

<?php 
if(isset($_POST['ok'])){
if(isset($_POST['item']) && $_POST['item'] != $_POST['chif']){
echo "vous n'avez pas entrer le bon chiffre";
}
else{
echo $_POST['chif'];
}
}
?>
</body>
</html>
Et sur la page de creation de l'image
<?php
session_start();
$im = imagecreate (70, 20);   
$background_color = imagecolorallocate ($im, 150, 100, 120);
$text_color = imagecolorallocate ($im, 255, 255, 255);
imagestring ($im, 4, 10, 2,  $_SESSION['chiffre'], $text_color);
imagepng ($im);
?>
Il n'y a pas de soucis, ca fonctionne, mais ma question est surtout de savoir si cela est suffisant et correct.

Merci pour vos explications :?

Mammouth du PHP | 19672 Messages

11 févr. 2006, 16:00

L'idée de base est bonne, cependant, il faut savoir que tu pourrais avoir affaire à des robots programmés avec un logiciel d'OCR (Reconnaissance des caractères) et c'est la raison pour laquelle beaucoup de captcha présentent des caractères déformés que les humains sont capables de lire mais qu'un robot ne reconnaîtra pas.

Donc ce qui serait à développer à mon avis, c'est un système chronométré. Un humain normal mettra un certain temps à remplir un formulaire. Un robot ne mettra qu'une fraction de seconde pour la même chose. Donc l'idée consisterait à enregistrer un microtime au chargement de la page de formulaire et un second lors du chargemet de la page de traitement, les deux dans des variables de session par exemple : en faisant la différence, si l'écart est inférieur à deux secondes par exemple, il y a toutes les chances pour que ce soit un robot qui ait actionné le formulaire. Plus le formulaire sera complexe, plus ce sera évident, d'autant plus si tous les champs du formulaire sont remplis.

Alors ce ne sont que des idées, je te laisse le soin de développer sur ce thème ;)
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Eléphant du PHP | 227 Messages

11 févr. 2006, 16:43

voila Cyrano, j'ai suivit ton conseil et j'ai fouillé un peu dans la doc officiel et adapter cela:
<?php 
$temps_dep = microtime(true);
usleep(3000000);
$temps_ar = microtime(true);
$time = $temps_ar - $temps_dep;

if(isset($_POST['ok'])){	
if(isset($_POST['item']) && $_POST['item'] != $_POST['chif'] && $time < 3000000){
echo "vous n'avez pas entrer le bon chiffre";
unset($_SESSION['chiffre']);
exit();
}
else{
echo $_POST['chif'];
}
}
?>
Je dois m'absenter, je reviens ce soir, mais pourrait tu m'indiquer si je suis sur la bonne voie, et surtout si le codage est correct ?
En tous les cas, apparamment, cela met quelques secondes à charger, mais es ce trop, pas assez ou faut-il modifier ma façon de procéder ?

Le but etant de comprendre ce que je fais.. Merci de ton aide
#-o

Mammouth du PHP | 19672 Messages

11 févr. 2006, 20:00

Je comprends mal ton départ: tu fais ta mesure de temps juste sur la page de traitement : c'est un peu sans intérêt. Je t'ai suggéré de capturer le premier microtime au chargement du formulaire, et le second dans la page de traitement. C'est le délai écoulé entre les deux qui est intéressant à mesurer : là, tu prends un premier au début du traitement, une pause de trois secondes et un second microtime: bon, ok, et alors ? comment pourrais-tu savoir de cette manière combien de temps il a fallu à l'internaute pour compléter le formulaire ?
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Eléphant du PHP | 227 Messages

11 févr. 2006, 23:20

ok, j'ai donc repris tes conseils et fait la chose suivante:
<?php $temps_dep = microtime(true); ?><!-- Debut de l'initialisation -->
<form method="post" action="" />
<img src="./captcha.php" alt="" /> &nbsp;&nbsp;
<input type="text" name="item" />
<input type="hidden" name="chif" value="<?php echo $_SESSION['chiffre'] ?>" />
<input type="submit" name="ok" />
</form>

<?php 
if(isset($_POST['ok'])){
$temps_ar = microtime(true);// Fin de l'initialisation
$time = $temps_ar - $temps_dep; // Calcul du temps
if(isset($_POST['item']) && $time < 300000){
echo $time;
unset($_SESSION['chiffre']);
}
else{
echo $time."<br>";
echo $_POST['chif'];
}
}
Cela ne fonctionne pas puisque le temps de calcul se fait entre le début du formulaire et au moment ou je clique sur ok donc moin des 3s que je voudrais imposer.
J'ai donc encore quelque chose qui m'échappe

8)

Mammouth du PHP | 19672 Messages

12 févr. 2006, 00:24

Tu t'y prends un peu de travers : d'autre part, tu oublies un point important que j'ai pourtant mentionné : l'enregistrement dans une variable de session du temps de départ : sinon, il ne sera pas transmis à la page de traitement et il faut éviter de le mettre dans un champ caché que pourrait lire le robot.

Tiens, regarde ça et essaye de voir si ce ne serait pas plus logique sous bien des points de vue ?
<?php
session_start();
if(isset($_POST['ok']))
{
    $temps_ar = microtime(true);// Fin de l'initialisation
    $time = $temps_ar - $_SESSION['temps_dep']; // Calcul du temps
    if(isset($_POST['item']) && $time < 300000)
    {
        echo $time;
        unset($_SESSION['chiffre']);
    }
    else
    {
        echo $time."<br>";
        echo $_POST['chif'];
    }
}
else
{
    $_SESSION['temps_dep'] = microtime(true);
?>
<!-- Debut de l'initialisation -->
<form method="post" action="" />
<img src="./captcha.php" alt="" /> &nbsp;&nbsp;
<input type="text" name="item" />
<input type="hidden" name="chif" value="<?php echo $_SESSION['chiffre'] ?>" />
<input type="submit" name="ok" />
</form>

<?php
}
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Eléphant du PHP | 227 Messages

12 févr. 2006, 13:23

J'ai donc repris ton raisonnement, effectivement bien plus cohérent que le mien (dieu merci) et j'en ai fait cela:
if(isset($_POST['ok'])){
    $_SESSION['temps_ar'] = microtime(true);
	$_SESSION['time'] = ($_SESSION['temps_ar'] -= $_SESSION['temps_dep']); // Valeur du temps écoulé
	$_SESSION['temp_spam_ok'] = 3000000; // Valeur de comparaison
	
	if($_SESSION['time'] < $_SESSION['temp_spam_ok'])
	{
		echo 'Le temp est inférieur à 3 secondes, donc peut être du spam'.'<br>';
		echo $_SESSION['time']; // temps écoulé
	}
	else{
	echo 'Le temp est supérieur à 3 secondes donc, certainement un humain'.'<br>';
	echo $_SESSION['time'];	// temps écoulé
		}
Et à l'initialisation ceux-ci:
<?php $_SESSION['temps_dep'] = microtime(true); ?>
<form method="post" action="" />
Jusque la ca à bien l'air de fonctionner avec un comparatif, par contre lorsque le temps écoulé est supérieur à 3s, il ne m'affiche pas le résultat la valeur du "else".

:)

Mammouth du PHP | 19672 Messages

12 févr. 2006, 13:29

Essaye un truc :
<pre>
<?php
var_dump($_SESSION);
?>
</pre>
Là, cherche tes variables de session et vérifie les valeurs.
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Eléphant du PHP | 227 Messages

12 févr. 2006, 14:21

Voila, j'ai donc controlé les valeurs des variables de session et constaté une incohérence dans le nombre, j'ai donc corrigé comme suit:
$_SESSION['time'] = ($_SESSION['temps_ar'] - $_SESSION['temps_dep']);
$_SESSION['temp_spam_ok'] = 3.0;
cela fonctionne. Suis je correct ? :D

Mammouth du PHP | 19672 Messages

12 févr. 2006, 14:26

Si ça fonctionne à ta satisfaction, c'est tout ce qui importe ;)

Le cas échéant, tu peux cliquer sur le bouton [Résolu]
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Eléphant du PHP | 227 Messages

12 févr. 2006, 14:37

Merci de ton aide Cyrano et bon dimanche ! 8)

Eléphant du PHP | 227 Messages

27 févr. 2006, 22:30

Bonjour à tous,

Je pensais avoir compris le principe, j'avais donc résolu ce post, mais à vrai dire, y a encore un truc que je pige pas, je le réouvre.

Voila ce bout de code en local, m'affiche un calcul avec un temps progressif, par contre chez mon hebergeur cela me produit l'inverse. Pourriez-vous m'aider à comprendre, merci
<?php
session_start();

if(isset($_POST['ok'])){
    $_SESSION['temps_ar'] = microtime(true);
	$_SESSION['time'] = ($_SESSION['temps_ar'] - $_SESSION['temps_dep']);
	$_SESSION['temp_spam_ok'] = 3;
	
		echo '<pre>';
			var_dump($_SESSION);
		echo '</pre>';	
	
	if($_SESSION['time'] < $_SESSION['temp_spam_ok'])
	{
		echo 'Le temp est inférieur à 3 secondes, donc peut être du spam'.'<br>';
		echo $_SESSION['time']; // temps écoulé
	}
	else{
	echo 'Le temp est supérieur à 3 secondes donc, certainement un humain'.'<br>';
	echo $_SESSION['time'];	// temps écoulé
		}
		
		}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" xml:lang="fr" />
<title>Test captcha</title>
<meta http-equiv="Content-type" content="image/png" />
</head>
<body>
<?php $_SESSION['temps_dep'] = microtime(true); ?>
<form method="post" action="" />
<input type="text" name="item" />
<input type="submit" name="ok" />
</form>
</body>
</html>

Eléphant du PHP | 227 Messages

27 févr. 2006, 23:34

Bon j'ai trouvé ca sur le site officiel:
function getmicrotime(){ 
    list($usec, $sec) = explode(" ",microtime()); 
    return ((float)$usec + (float)$sec); 
    }
J'ai donc modifié, mon code en appelant non plus part
microtime(true)
mais part l'appel de la function getmicrotime().

Ca fonctionne.
:D

Utilisateur anonyme Fou !
Invité n'ayant pas de compte PHPfrance

02 mars 2006, 17:18

J'aimerais savoir si ce systeme Anti-Spam est fonctionnel finalement et qu'il protege reellement contre les spams ?

Merci