Travaux : Php

Le captcha : rebutons les robots ! (dans Php, le 17/04/2008 à 19h 16min)

Si vous avez essayé de poster un commentaire sur un des articles, vous avez sûrement vu ça :

image de l'article

C'est ce qu'on appelle un captcha :
Citation : Wikipédia
Ce test est utilisé sur Internet dans les formulaires pour se prémunir contre les soumissions automatisées et intensives réalisées par des robots malveillants.
Je vous laisse lire l'article sur Wikipédia, qui est bien fait, si vous êtes intéressé.



Celui qu'il y a pour les commentaires est moins tordu que celui présenté ci-dessus, pour simplifier sa lecture par les visiteurs. Si des robots arrivent à passer, je n'aurais qu'à le corser ^^ .
Ce qui nous intéresse est la particularité de celui-ci, créé par moi-même : comme vous pouvez le voir, il bouge (si si, regardez bien ^^ )

Suite à une discussion sur le Site du Zéro, je me suis demandé comment on pourrait faire un truc original, parmis les milliers de formes de captcha déjà existantes. Et j'ai eu l'idée de me servir d'une particularité qui distingue l'Homme de l'Ordinateur : notre oeil, et plus précisément, la persistance rétinienne.

A partir de là, j'ai essayé de faire un captcha animé, de manière à ce que si on regarde une seule image à la fois, il soit très dur de lire le code. Je génère donc un captcha en GIF animé, afin de profiter de cette particularité de notre oeil. Je vous laisse juger sur cette capture du captcha présenté ci-dessus, qui montre donc une seule frame du captcha :

image de l'article

On se rend bien compte que c'est bien plus dur à comprendre.
La principale méthode utilisé par les robots pour casser les captchas, c'est de distinguer les zones de différentes couleurs, et de tenter de reconnaitre la forme de la lettre correspondante. Une des parades est donc de faire toutes les lettres de la même couleur, pour rendre la distinction plus difficile, de les faire se toucher, de brouiller les lettres...
Je pense que de ce point de vue là, une image fixe de mon captcha est assez dure à décrypter pour un bot. La faiblesse viendra peut-être du fait qu'on puisse "découper" le captcha en plusieurs images, et en les comparant, regarder ce qui bouge moins que le reste pour savoir où est le texte, et ce qu'il dit.
C'est pour ça que je fait en sorte que d'une image à l'autre, le texte se déplace de quelques pixels, aléatoirement, afin de rendre plus difficile sa localisation, sans pour autant trop gêner l'utilisateur.

Voici le code complet, pour ceux que ça intéresse : ( GIFEncoder.class.php est une classe créée par László Zsidi, http://gifs.hu visible ici : GIFEncoder.class.php )
Code : PHP
  1. <?php
  2. include "GIFEncoder.class.php"; //la classe qui se charge de l'encodage du gif
  3.  
  4. function cara_aleatoire($longueur){ //fonction qui genere une chaine aleatoire de la longueur voulue
  5.    $retour = "";
  6.    $chaine = "ABCDEFGHIJKLMNPQRSTUVWXYZ123456789";
  7.    for($i=0; $i<$longueur; $i++)
  8.    {
  9.          $retour .= $chaine[mt_rand(0,strlen($chaine)-1)];
  10.    }
  11.    return $retour;
  12. }
  13.  
  14. /*Parametrage du captcha*/
  15. $captcha_largeur = 220;
  16. $captcha_hauteur = 80;
  17. $longueur_texte = 6;
  18. $police = 'ariblk';
  19. $taille_texte = mt_rand(25,35);
  20. $angle_texte = mt_rand(-10,10);
  21. $nb_trait = 500;
  22. $duree_image = 5; //milliseconde
  23. $nb_image = 4; //nombre de frames du gif
  24.  
  25. /*Declaration des couleurs*/
  26. $image = imagecreatetruecolor($captcha_largeur, $captcha_hauteur);
  27. $blanc = imagecolorallocate($image, 255, 255, 255);
  28. $blanc_alpha = imagecolorallocatealpha($image, 255, 255, 255, 50);
  29. $noir = imagecolorallocate($image, 0, 0, 0);
  30. $noir_alpha = imagecolorallocatealpha($image, 0, 0, 0, 50);
  31.  
  32. $texte = cara_aleatoire($longueur_texte);
  33.  
  34. $coord = imagettfbbox($taille_texte, $angle_texte, $police, $texte);
  35. $zone_abscisse = $captcha_largeur-$coord[2];
  36. $position_x_texte = mt_rand(10, $zone_abscisse-10);
  37. $position_y_texte = mt_rand(abs($coord[5])+10, $captcha_hauteur-10);
  38.  
  39.  
  40. for($j = 0; $j<$nb_image; $j++){ //pour chacune des images constituant le gif
  41.    imagefilledrectangle($image, 0, 0, $captcha_largeur, $captcha_hauteur, $noir);
  42.    
  43.    /*Trace des lignes blanches*/
  44.    for($i = 0; $i<$nb_trait; $i++){
  45.       $x = mt_rand(0, $captcha_largeur-2);
  46.       $y = mt_rand(0, $captcha_hauteur);
  47.       $longueur = mt_rand(1,10);
  48.       imageline($image, $x, $y, $x+$longueur, $y, $blanc);
  49.       
  50.       $x = mt_rand(0, $captcha_largeur);
  51.       $y = mt_rand(0, $captcha_hauteur-2);
  52.       $hauteur = mt_rand(1,10);
  53.       imageline($image, $x, $y, $x, $y+$hauteur, $blanc);
  54.    }
  55.  
  56.    /*Affichage du texte*/
  57.    imagettftext($image, $taille_texte, $angle_texte, $position_x_texte+mt_rand(-2,2), $position_y_texte+mt_rand(-2,2), $blanc, $police, $texte);
  58.  
  59.    /*Trace des lignes noires*/
  60.    for($k = 0; $k<$nb_trait; $k++){
  61.       $x = mt_rand(0, $captcha_largeur-2);
  62.       $y = mt_rand(0, $captcha_hauteur);
  63.       $longueur = mt_rand(1,10);
  64.       
  65.       imageline($image, $x, $y, $x+$longueur, $y, $noir);
  66.       
  67.       $x = mt_rand(0, $captcha_largeur);
  68.       $y = mt_rand(0, $captcha_hauteur-2);
  69.       $hauteur = mt_rand(1,10);
  70.       
  71.       imageline($image, $x, $y, $x, $y+$hauteur, $noir);
  72.    }
  73.    
  74.    ob_start();
  75.    imagegif($image);
  76.    $images[] = ob_get_clean();
  77.    $temps[] = $duree_image;
  78. }
  79.  
  80. $gif = new GIFEncoder ($images, $temps, 0, 2, 0, 0, 0, "bin"); //encodage du gif
  81.    
  82. header ("Content-type:image/gif");
  83. echo $gif->GetAnimation(); //et envoie au navigateur
  84. ?>


[6 commentaire(s)]