7.PHP pour le web

7.4.Captcha (anti robot) pour formulaire

7.4.4.Intégration du captcha dans un formulaire

7.4.4.1.Génération

D'un point de vue mise en page, l'intégration du captcha dans le formulaire consiste simplement à afficher l'image dans la page HTML. Ce qui se fait donc simplement par un
<img src="captcha.php" alt="captcha"/>
L'aspect le plus intéressant est évidemment l'intégration d'un point de vue fonctionnel. Et voici ce que l'on veut:
  • Générer un mot et l'afficher: le captcha
  • Permettre la saisie de ce mot: un champ supplémentaire dans le formulaire
  • Une fois le formulaire "soumis", comparer le mot saisi et le mot généré: la validation du formulaire.
L'affichage du formulaire et la validation du formulaire étant 2 requêtes distinctes. Il faut trouver le moyen de mémoriser le mot qui a été généré par le captcha pour pouvoir l'avoir à disposition au moment de la validation. Pour cela, nous ferons appel aux sessions[c'est quoi?] (le moyen le plus simple de mémoriser une donnée sans la rendre visible).
Le mot généré par le captcha peut être connu en appelant la méthode getPhrase() de l'objet Text_CAPTCHA. Il sera alors stocké en session sous un identifiant quelconque ('sess_captcha' semble, ceci dit, un choix judicieux et nous eviterons 'captcha' pour ne pas entrer en conflit avec l'objet $captcha si dans la configuration PHP on register_globals = On). Le code complet du script d'affichage du captcha sera donc en fait:
<?php
session_start();

require_once('include_path_inc.php');
require_once('Text/CAPTCHA.php');

// Instanciation d'un objet Text_CAPTCHA de type Image
$captcha = Text_CAPTCHA::factory('Image');

// Initialisation
$err = $captcha->init();
if (PEAR::isError($err)) {
    die("Erreur d'initialisation du CAPTCHA:".$err->getMessage());
}

// Stockage en session du mot 
$_SESSION['sess_captcha'] = $captcha->getPhrase();
// ATTENTION: Si la cle de session est simplement 'captcha' et que
// register_globals = On, l'objet $captcha sera ecrase par la variable de sess.

// Recuperation de l'image au format PNG
$png = $captcha->getCAPTCHAAsPNG();
if (PEAR::isError($png)) {
    die("Impossible de creer l'image".$png->getMessage());
}

// "Affichage" de l'image
header("Content-Type: image/png");
echo $png;
?>
Vous notez l'ajout de session_start(); et $_SESSION['sess_captcha'] = $captcha->getPhrase();
Le formulaire quant à lui pourra contenir autant de champs que voulu mais devra obligatoirement contenir le champ de saisie du mot affiché dans le captcha. Pour notre exemple, nous baptiserons ce champ 'captcha' (pas bête, non?). Ce qui donne le schéma suivant:
<form method="post">
   <!-- Inserer les vrais champs du formulaire (nom, prenom, id, etc.) -->
   <img src="captcha.php" alt="captcha" />
   Copier le mot ici: <input type="text" name="captcha" />
   <input type="submit" value="Sauver"/>
</form>
qui donne