Aller au menu - Aller au contenu

[Plan du site] Vous êtes ici --- > Le Site du Zér0 > Les tutoriels > Non-Officiels > Site Web > PHP > Optimisation & Sécurité > Lecture du tutoriel

Créer une image de validation

Avatar
Auteur : DeadPixel
Créé : le 23/05/2006 19:01:16
Modifié : le 09/10/2007 12:07:39
Noter et commenter ce tutoriel
Imprimer ce tutoriel
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)
Il peut arriver que votre site soit assez fréquenté, ou que des bots s'attaquent à votre système de membres ou de commentaires, et vous risquez vite d'en avoir marre de liens récurrents vers des sites vendant du Viagra à -30 % en Tchécoslovaquie. Pour combler ça, je vais vous aider à créer un système de validation par image, histoire de ne laisser que l'humain accéder à votre travail. ;)

Pour l'exemple ci-dessous, histoire de simplifier les choses, je vais juste le faire pour une page de protection ; ça fera du code en moins, et c'est tout aussi pratique, car vous pourriez avoir affaire à un bot qui va chercher des combinaisons de mots de passe pour accéder à une page secrète...
Sommaire du chapitre :

Organiser le script

D'abord, faisons un survol des fichiers et infos qu'on va créer. Tout d'abord, les fichiers :
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 : PHP
1
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 ? :magicien:

Créer l'image

Maintenant, créons le fichier img_verif.php. Ce fichier est composé de 2 parties :

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 : PHP
1
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 : PHP
1
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 : Image utilisateur. Pour connaître les équivalents hexadécimaux -> RVB, utilisez un outil tel que celui-ci (ou celui-là :D ).

Ensuite, on va dessiner l'image. Commençons par des maths Image utilisateur ; je vous rappelle la syntaxe d'imagestring() :
Code : PHP
1
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 :lol: )

Le résultat final de cette ligne est donc :Code : PHP
1
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 ( :o ), je vous fais la fin qui est encore plus simple :

Code : PHP
1
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).

Résumé des scripts

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';
}
?>

Encore un peu ?

Vous pouvez évidemment faire d'autres choses :p ! 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 : Image utilisateur (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 :p et le résultat sera :
Image utilisateur
(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 : PHP
1
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 :
Image utilisateur


Voilà, c'est fini ! Évidemment, rien ne vous interdit de faire des modifications à ce script pour l'adapter à tous vos besoins. :p Je précise que je me suis (un peu :-° ) basé sur le tuto de mEga :) .

PS : Merci de ne PAS m'envoyer de message privés à propos du tutoriel, les commentaires sont là pour ça.
Auteur : DeadPixel
Noter et commenter ce tutoriel
Imprimer ce tutoriel

Changer de design | En savoir plus | Plan du site | Politique d'accessibilité | Règles | Fil RSS | XHTML 1.0 | CSS 2.0
Édité par Simple IT SARL : Nous contacter | Revue de presse | Publicité

Y'a plus rien à lire, faut remonter maintenant !

Hébergement web - Correction de tutoriels - Créer un site
Vous souhaitez apparaître ici ? Contactez-nous.

Nombre de connectés 289 Zéros connectés | Requêtes SQL 7 requêtes | Temps de génération de la page : Total (SQL) 0.225s (0.2131s)