Sans titre-1

Réaliser un captcha simple

Le but de ce tutorial va consister à l’élaboration d’un Captcha à l’aide du langage PHP, pour cela, on abordera dans ce tuto, les sessions et 2 ou 3 fonctions de la librairie GD qui permettent de générer des images dynamiquement.

 

Générer une image

<?php
// Démarage d'une session
session_start();
// création d'une chaine de caractères (faire attention à ne pas avoir d'éléments qui peuvent parraitre confus tels que 1,l,I,0,O....
$caracteres = "34589ABCDEFHKMNPQRTWXYZ";
// Initialisation du code finale
$code = '';

// Tant que le code n'a pas 4 caractère, on lui en ajoute un aléatoirement à partir de la chaine de caractères
while(strlen($code) != 4){
	$code .= $liste[rand(0,strlen($liste))];
}

//On va maintenant générer l'image
// on crée une image de 50 pixels par 20 pixels :
$img = imageCreate(100, 30);

//On lui attribue des couleurs
$white = imageColorAllocate($img,255,255,255);
$noir = imageColorAllocate($img,0,0,0);

//On crée le header qui permettra de savoir que ce document est une image
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header("Content-type: image/jpeg");

/* On insère la variable $code dans l'image avec la fonction ImageTTFText
 Cette fonction permet aussi de choisir la police avec laquelle on écrit, donc autant en mettre une qui soit le plus difficile à lire*/
ImageTTFText($img,30,0,15,25,$noir, 'polices/manuscrit.ttf',$code);
// on crée ensuite l'image jpg compréssé à 40%
imagejpeg($img,'',40);
imageDestroy($img);

/* Pour finir On initialise la variable $_SESSION['code'] avec le code aléatoire, cette variable se retrouvera donc dans la page suivante crypté en md5...*/
$_SESSION['code']= md5($code);
?>

Ce script est la base de cette petite fonctionnalité et permet de créer une valeur à coder qui est ensuite crypté en MD5 dans une session et permet de générer une image avec le code écrit. Enregistrez ce fichier en le nommant « cryptimage.php ».

Réaliser le formulaire

Voici à quoi pourrait ressembler le formulaire à présent qui est dans le fichier « contact.php » :

<form method="post" action="contact.php">
  <fieldset>
    <legend>Formulaire de contact</legend>
    <label for="message">Message</label>
    <textarea rows="10" cols="25" name="message" id="message"></textarea>
    <label for="code">Code à reproduire</label>
    <img title="Captcha" src="cryptimage.php" alt="Captcha" />
    <input id="code" name="verif" type="text" />
    <button type="submit">Envoyer</button>

  </fieldset>
</form>

Nous appelons notre script « cryptimage.php » directement à partir de la balise img, comme celle ci renvoie une image. Maintenant nous allons vérifier, si le formulaire a été validé, la valeur du champ $_POST['verif'] avec la variable de session $_SESSION['code']. Ce qui donne ceci:

if (isset($_POST['message'])){
    	 $erreurs=array();
    	 session_start(); //attention ceci doit être envoyé avant même l'entete HTML!
          if($_SESSION['code'] != md5($_POST['verif'])) {
          	$erreurs[] = 'Erreur dans le code de vérification...';
          }
	//petite vérification rapide des autres champs
      foreach($_POST as $key => $value){
        if(empty($value)){
          if(empty($erreurs)){
            $erreurs[] = 'Certains champs n\'ont pas été renseignés';
          }
          $erreurs[] = 'le champ '.$key.' n\'est pas rempli';
        }
      }
   }

//...votre page HTML

	     if(!empty($erreurs) && !empty($_POST['message']){ //vérifie si le tableau erreurs existe et est vide sinon il les affiche
            echo '<div class="error">
                    <ul>';
            for($i=0;$i<count($erreurs);$i++){
            	echo '<li>'.$erreurs[$i].'</li>';
            }
            echo '</ul>
                </div>';
          }
          else{
   		//traitement du formulaire
    	}

Notez que l’initialisation de la session par la fonction session_start(); doit se faire au tout début de votre script. Cette subtilité est une source fréquente d’erreurs.

Si PHP et les sessions ne sont pas votre tasse de thé voici ce qui se passe lors de l’éxécution de ce script:
Captcha schéma

Notre script peut certainement être amélioré, et notamment du fait que des non-voyants ne pouront pas reconnaître la chaine. Aujourd’hui beaucoup de captcha sont maintenant accompagnés d’un extrait sonore pour eux.

Enfin, il pourra aussi être amélioré afin qu’il soit moins compréhensible pour un robot (ajout de lignes aléatoires, changement de couleurs, fond en dégradé, etc).

16 commentaires

S'abonner au RSS des commentaires
  1. Emile
    Posté le 22/09/2011 à 10h21

    Bonjour,

    Le 3ieme paramètre de la fonction imagejpeg() indique la qualité et non la compression

    0 => compression maximale
    40 => compression à 60%
    100 => compression à 0%

    50 est un bon compromis.
    Emile

  2. François
    Posté le 07/02/2011 à 23h20

    Oui tu as tout à fait raison,
    ca fait parti des petits plus smile
    Sinon le fait de choisir une police un peu fantaisiste ca joue pas mal… Enfin après je suis pas un robot mais j’imagine que oui^^

  3. eBuildy
    Posté le 06/02/2011 à 19h44

    Autre bug aussi, qui se passe de façon aléatoire celui la ;-(

    strlen() renvoit la taille de la chaîne ! Donc il faut penser à ajouter – 1 :

    $liste[rand(0,strlen($liste) - 1)];

    Egalement, pour réaliser un vrai Captcha facilement, il faut partir d’une image background déjà un peu camouflée et écrire par dessus:

    $img = imagecreatefromjpeg(‘images/captcha_bg.jpg’);

    Egalement lors de l’écriture, on peut jouer sur l’angle et la position aléatoirement:

    ImageTTFText($img,20,(int)rand(-20,20),rand(25,100),rand(30,60),$red,EB_ROOT.’images/AGENTORANGE.TTF’,$code);

  4. air jordan 2
    Posté le 20/11/2010 à 9h03

    Avant tout merci pour ce partage de code.

    Maintenant, j’ai des doutes pour l’implanter…

  5. peoples
    Posté le 16/11/2010 à 23h32

    oui je confirme un peti bug dans le code mince

  6. jhice
    Posté le 30/03/2010 à 11h59

    Il y a un bug dans le code :

    $caracteres = $liste !

    donc pour ceux qui seraient bloqués ici, ligne 5, remplacer

    $caracteres = "34589ABCDEFHKMNPQRTWXYZ";
    par :
    $liste = "34589ABCDEFHKMNPQRTWXYZ";

  7. HPWEST
    Posté le 29/11/2009 à 13h17

    Bonjour!!! actuellement embeter sur mon site avec des robots, j’ai trouver sur votre site ce tuto mais malheureusement je n’arrive pas a l’installer. pouvez-vous m’aider a y voir un peu clair pour que je puisse installer ce Captcha.

    merci à vous amicalement.

  8. Sexy Lady
    Posté le 04/11/2009 à 17h14

    Bonjour,

    Avant tout merci pour ce partage de code.

    Maintenant, j’ai des doutes pour l’implanter…
    Est ce que le code est fiable ou a été réparé depuis cette fameuse boucle infinie ?

    Je vous remercie d’avance pour une réponse

  9. François
    Posté le 16/10/2009 à 22h20

    Salut!!!Tout d’abord si il y’a un problème dans le code, cela ne fera pas planté ton navigateur mais seulement ton serveur (boucle infinie apparemment)

    Apparemment ta chaine ne se crée pas vraiment

    vérifie que tu as bien ta variable $liste="tescaracteresabcdefgh…12345..";

    Sinon ton adresse localhost personne ne peut y accéder à par toi wink

  10. B4rto
    Posté le 14/10/2009 à 10h57

    Bonjour, j’ai un problème au nivo de la création du captcha:

    en effet cette ligne fait planté mon mozzila, :
    while(strlen($code) != 4){

    $code .= $liste[rand(0,strlen($liste))];
    Deja la page met 3 ans a charger et en après, sa me dit que la variable liste n’est pas définit ce qui est plutot vrai.
    Notice: Undefined variable: liste in C:\Program Files\wamp\www\\cryptimage.php on line 13

    Donc j’ai test en métant la variable $caracteres qui me parraisait plus logique et la sa me renvoi l’url de la page ou je me trouve à savoir.
    http://localhost/www/index.php?p=cryptimage

    Donc je pige pas trop.

  11. Robin
    Posté le 07/07/2009 à 20h06

    Sa marcher chez vous?

  12. Jasse29
    Posté le 02/05/2009 à 3h42

    Très utile, je vais pouvoir la combine que j’utilisais jusqu’à aujourd’hui

  13. Francois
    Posté le 20/03/2009 à 16h46

    Ah oui je devais pas connaitre à cette epoque! Sinon tout est dans les morceaux de code…

  14. alain bashung
    Posté le 20/03/2009 à 15h49

    c’est un peu l’arnaque, tu files pas les sources pour çui là!

  15. François
    Posté le 07/03/2009 à 13h46

    Oui, par contre tu dois faire ta verification du tableau d’erreurs avant l’affichage de la balise form histoire de mettre le message juste au dessus du formulaire, et si il est vide tu n’affiche pas le formulaire tout simplement et tu traites les données

  16. thvi
    Posté le 07/03/2009 à 11h16

    Bonjour,

    Le troisième listing de scripts s’insère dans le fichier contact.php ?

    <?php // validation du formulaire ?>
    <html>
    <head>

    </head>
    <body>
    <form>
    </form>
    <?php // traitement du formulaire ?>
    </body>
    </html>

    Cordialement.

Laisser un commentaire

Votre e-mail ne sera jamais publié ni communiqué. Les champs obligatoires sont indiqués par *

*
*

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>