Vous vous apprêtez à lire un tutoriel rédigé par un membre de ce site. Malgré tout le soin que ce membre a pu apporter au tutoriel, nous ne pouvons pas garantir que les informations contenues sur cette page sont exactes à 100%. Merci de garder cela en tête lorsque vous lirez cette page ;o)
D'abord, faisons un survol des fichiers et infos qu'on va créer. Tout d'abord, les fichiers :
- protection.php : c'est le fichier dans lequel on insérera l'image et où on devra écrire son contenu.
- img_verif.php : c'est le fichier qui va générer l'image, avec du GD.
Pour faire fonctionner les deux ensemble, soyons coordonnés : on va utiliser une
session dans chaque page pour récupérer les données d'une page à une autre. Faisons un plan en gros de ce que ça peut donner :
protection.php :
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13 | <?php
session_start();
// Si le code généré est le même que celui qu'on a donné...
if ($_SESSION["image"] == $_POST["code"])
{
// ...alors se connecter.
}
else
{
echo "Désolé, le code de l'image de vérification ne correspond pas à celui que vous avez entré.";
?>
<!-- Dans le formulaire pour se connecter... -->
<img src="img_verif.php" /><input type="text" name="code" />
|
Et dans
img_verif.php :
Code : PHP1
2
3
4
5
6 | <?php
session_start();
// Générer le code aléatoirement et le stocker dans $code
$_SESSION["image"] = $code;
// Ensuite générer l'image avec le contenu de $code...
?>
|
Comme vous pouvez donc le constater, on utilise donc une variable super-globale de session,
image, dans
img_verif.php. Elle correspond au code généré (en version texte, avant d'être généré en image). Ensuite, lors de l'envoi du formulaire, on compare le code généré avec celui envoyé. Simplissime, non ?
Maintenant, créons le fichier
img_verif.php. Ce fichier est composé de 2 parties :
- une partie PHP "texte" pour générer un code aléatoire et le stocker
- une partie GD pour créer l'image.
Générer le code
Commençons donc par la partie du code : pour en créer un aléatoirement, on va créer une variable qui contient tous les chiffres et les lettres, puis on va créer une boucle pour en extraire 5 au hasard.
Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12 | <?php
session_start(); // N'oubliez pas de créer la session
$liste = "abcdefghijklmnopqrstuvwxyz123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$code = ''; // On crée une variable $code
while(strlen($code) != 5) {
$code .= $liste[rand(0,63)];
}
// Puis on inclut $code dans une variable de session, celle qui sera comparée avec le reste.
$_SESSION['code']=$code;
?>
|
Pour ceux qui n'auraient pas compris la boucle, je traduis en français :
"tant que la longueur de
$code n'est pas 5, je prends un nombre au pif dans
$liste."
Et pour prendre un nombre au pif, c'est bien le
[rand(0,63)] qui est utilisé (pour plus d'infos sur
rand(), regardez
ici).
Créer l'image
Ensuite vient la création de l'image avec GD (il doit être activé : pour plus d'infos, relisez
le cours à ce sujet 
).
Alors révisons un peu, et créons dans l'ordre. Donc d'abord, les headers :
Code : PHP1
2 | header('Content-type: image/jpeg'); // On définit le type de fichier
header('Cache-Control: no-store, no-cache, must-revalidate'); // L'image ne doit pas être enregistrée dans le cache, puisqu'elle va être changée à chaque fois.
|
Ensuite, choisissons les propriétés :
Code : PHP1
2
3
4 | $img = imageCreate(40, 15); // Créer une image de 40x15 pixels
$fond = imageColorAllocate($img,0,0,0); // On choisit la couleur du fond (en RVB)
$texte = imageColorAllocate($img,255,255,255); // Idem, mais pour la couleur du texte
$police = 2; // La taille de la police (entre 1 et 5, pré-inclues dans PHP)
|
Voilà, là, c'est vous qui voyez. Si on suit mon exemple, vous aurez une image comme ça :

. Pour connaître les équivalents hexadécimaux -> RVB, utilisez un outil tel que
celui-ci (ou
celui-là 
).
Ensuite, on va dessiner l'image. Commençons par des maths

; je vous rappelle la syntaxe d'
imagestring() :
Code : PHP1 | imagestring($image, $police, $x, $y, $texte_a_ecrire, $couleur);
|
Puisque je vous ai laissé choisir la taille, il va falloir adapter ce script pour que
$x et
$y soient centrés par rapport à l'image. Rien de bien compliqué : pour calculer
$x c'est
largeur de l'image divisée par 4, et pour
$y c'est
hauteur divisée par 8 (pour les anti-matheux complets :
Démarrer ->
Exécuter ->
calc 
)
Le résultat final de cette ligne est donc :
Code : PHP1 | imageString($img, $police, 5, 1.875, $code,$texte);
|
En remplaçant donc 5 et 1.875 par d'autres nombres, si vous avez changé la taille de l'image. Facile, hein ?
Allez, comme vous avez fait un gros effort (

), je vous fais la fin qui est encore plus simple :
Code : PHP1
2 | imagejpeg($img,'',30);
imageDestroy($img);
|
Qu'est-ce ? Hé bien la fonction
imagejpeg() va faire écrire à PHP l'image que vous avez composé dans
$img. Le paramètre 30 va régler la qualité de l'image JPEG à 30 %. Pourquoi ? Car les pirates évoluent, et leurs outils avec ; par conséquent, certains bots savent lire les chiffres et lettres en reconnaissant les caractères des polices PHP. Mais si on dégrade la qualité, ils ne seront plus capables de faire ça

: si vous voulez le modifier, restez entre 15 et 45 %, histoire de faire un compromis entre lisibilité et protection.
Quand à
imageDestroy(), il sert simplement à détruire l'image (ce qui est utile ici puisqu'elle va changer à chaque fois).
Vous avez relu et relu, mais votre code ne marche toujours pas ? Voici les codes complets :
img_verif.php :
Secret (cliquez pour afficher)Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 | <?php
session_start(); // Créér la session
$liste = "abcdefghijklmnopqrstuvwxyz123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$code = '';
// Mettre 5 caractères aléatoirement dans $code...
while(strlen($code) != 5) {
$code .= $liste[rand(0,63)];
}
// ...et le mettre dans la session.
$_SESSION['code']=$code;
header('Content-type: image/jpeg'); // On définit le type de fichier
header('Cache-Control: no-store, no-cache, must-revalidate');
// L'image ne doit pas être enregistrée dans le cache, puisqu'elle va être changée à chaque fois.
$img = imageCreate(40, 15); // Créer une image de 40x15 pixels
$fond = imageColorAllocate($img,0,0,0); // On choisit la couleur du fond (en RVB)
$texte = imageColorAllocate($img,255,255,255); // Idem, mais pour la couleur du texte
$police = 2; // L'ID de la police (entre 1 et 5, pré-inclues dans PHP)
imageString($img, $police, 5, 1.875, $code,$texte); // Ecrire le code sur l'image
imagejpeg($img,'',30); // Image de mauvaise qualité histoire de tromper les bots
imageDestroy($img); // Détruire l'image
?>
|
Et pour l'utiliser dans une page (je prends ici l'exemple d'une page de connexion avec juste un MDP), elle se base sur le
TP de M@teo21 :
Secret (cliquez pour afficher)Code : PHP 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 | <?php
session_start();
if (isset($_POST['mot_de_passe']) AND isset($_POST['code']))
{
$mot_de_passe = $_POST['mot_de_passe'];
$code = $_POST['code'];
}
else
{
$mot_de_passe = "";
$code = "";
}
if ($mot_de_passe == "kangourou" AND $code == $_SESSION['code'])
{
session_unset();
session_destroy();
// Mettez votre page secrète ici :-°
echo "Vous êtes entrés sur la page secrète !!!";
}
else
{
echo 'Désolé, mais le mot de passe ou le code de vérification ne correspondent pas à ceux que vous aviez à entrer';
}
?>
|
Vous pouvez évidemment faire d'autres choses

! Quoi comme ?
Accès malvoyants
Évidemment, ça peut poser un problème puisque ce truc n'est pas à ranger dans la catégorie "Accessibilité"... S'il s'agit d'une inscription, mettez un lien pour le contact afin de faire une inscription manuelle. Sinon, vous pouvez suivre le défi pour créer tout ça en sons
ici.
Un fond en image !
Pour un peu plus de protection contre ces bots qui lisent aussi les images, vous pouvez mettre un fond, façon "inscription du SdZ" (si vous vous en souvenez

). Pour cela, créez une image de la dimension voulue avec un truc sensé rester lisible. Ici je vais mettre des rayures :

(j'ai fait un fichier 40 x 15 pour que ça colle.)
Pour l'incruster dans l'image, on va remplacer
imageCreate(40,15) par
imagecreatefromjpeg("rayures.jpg"). Tout simplement

et le résultat sera :
(oui0 c'est assez illisible, c'est un des inconvénients... Si ça l'est trop chez vous, mettez une faible opacité aux rayures et prenez une grande taille d'écriture (donc une image plus grande

).
Une ombre au texte
Si on mijote dans la surprotection, on peut aussi le faire autrement... Rajoutons donc une petite ombre au texte ; ça protégera davantage votre code des bots et, en plus, ça sera plus beau. Mais comment faire ça ? En mettant deux textes, mais l'ombre avec une autre couleur (de préférence gris pour du texte noir), et en le décalant de 1 ou 2 pixels.
Évitez quand même de mélanger cette technique avec les rayures, car ça deviendra illisible ! En revanche, vous pouvez quand même prendre une image de fond plus simple (barres, dégradés...)
Concrètement, cela donne :
Code : PHP1
2
3
4
5 | $texte = imageColorAllocate($img,0,0,0); // Choisir la couleur du texte...
$ombre = imageColorAllocate($img,204,204,204); // ...et de l'ombre
imageString($img, $police, 7, 3.875, $code,$ombre); // Ecrire d'abord l'ombre
imageString($img, $police, 5, 1.875, $code,$texte); // Puis le code noir
|
Si vous êtes un peu graphiste et habitué des calques, vous vous demanderez pourquoi mettre d'abord l'ombre puis le texte normal. Dans un logiciel de création graphique/PAO, les calques sont dans l'ordres "en haut = premier plan, en bas = arrière-plan". Eh bien dans GD, c'est l'inverse ; on commence par l'arrière-plan puis on passe au premier plan.
Pour cette technique je vous conseille, comme pour l'image de fond, de mettre une grande police (donc grande image). Dans mon exemple, le résultat final sera :