Image de l'article Un code de sécurité PHP pour vos formulaires, partie 2

Un code de sécurité PHP pour vos formulaires, partie 2

Si vous prenez cet article en cours, voici les liens vers les 3 parties. Je vous conseille de commencer la lecture par la première partie puisque c'est progressif.

  1. Création d'un code de sécurité
  2. Amélioration du code de sécurité
  3. Vérification

Un code de sécurité est utile pour éviter que des robots spammeurs ne pollues votre site, mais il ne faut pas compliquer la vie des vrais utilisateurs pour autant.

En leur imposer de retaper des expressions tel que "czdv bqyir", "evkk drvm" ou encore "mbj rpwbu" vous risquez de perdre des commentaires car trop compliqué à écrire et trop facilement sujet à des erreurs de frappe.

Pour corriger le tir nous allons utiliser des mots réels.

Utilisation d'un dictionnaire

Un dictionnaire c'est une série de mot, sous forme de chaîne de caractères, array, données xml, table SQL, etc. Dans cet exemple j'utilise une chaîne de caractères.

La fonction suivante renvoie un ou plusieurs mots extrait de la variable $aWordLst. La fonction attend un tableau (array) mais vous pouvez passer du texte, elle effectuera la conversion.


function RandomWordFromArray($aWordLst, $WordNb=1){
	if(!is_array($aWordLst)) $aWordLst = explode(' ', $aWordLst);
	$str = '';
	$max = count($aWordLst)-1;
	for($i=0; $i<$WordNb; $i++){
		if($WordNb>1 && $i>0) $str .= ' ';
		$str .= $aWordLst[rand(0, $max)];
	}
	return $str;
}

Il faut ensuite créer une variable qui va contenir les mots qu'on souhaite utiliser et les passer à la fonction RandomWordFromArray().

Je vous conseille d'utiliser des mots de 5 à 8 caractères et d'éviter les accents ainsi que les majuscules. Vous pouvez utiliser le site liste-de-mots.com pour trouver l'inspiration.


$dico = 'balle base biche boire boule buche canard cercle chou cours courir croire dire dormir entier facile genou hibou image impair lire liste manger marcher montage monter mousse pierre pion poule pull quart scie signe temps valoir voir wagon';
$txt = RandomWordFromArray($dico, 2);

code sécurité niveau 1 : captcha niveau 1

Démonstration

Ajouter des lignes aléatoires

Nous allons commencer par ajouter quelques traits aléatoire dans le fond. Nous avons besoin d'un paramètre supplémentaire pour définir le nombre de lignes à dessiner.


function CaptchaImage($aText='', $aPath='', $aWidth=200, $aHeight=50, $aNbLine=0){

Pour dessiner une ligne avec GD image on utilise la fonction imageline() qui attend 6 paramètres :

  1. La ressource image créer avec imagecreatetruecolor()
  2. Coordonnée X1
  3. Coordonnée Y1
  4. Coordonnée X2
  5. Coordonnée Y2
  6. Une couleur obtenue avec imagecolorallocate()

Il suffit de placer le code suivant avant l'affichage du texte.


// active l'anti-aliasing
imageantialias($img, true);
// dessine quelques traits
for($i=0; $i<$aNbLine; $i++){
	// génère une couleur aléatoire
	$r = rand(150, 255);
	$v = rand(150, 255);
	$b = rand(150, 255);
	// créer la couleur
	$color = imagecolorallocate($img, $r, $v, $b);
	// dessine la ligne
	imageline($img, 0, rand(-50, $aHeight+50), $aWidth, rand(-50, $aHeight+50), $color);
}

code sécurité niveau 2 : captcha niveau 2

Démonstration

Notez l'appel à imageantialias($img, true); pour activer l'anti aliasing de l'image.

Utiliser une police TTF en PHP

La police par défaut dans GD Image n'est pas très sexy, elle est limitée en dimension (utilisable de 1 à 6 seulement) et ne dispose d'aucune option (gras, italique, etc).

Heureusement il est possible d'utiliser n'importe quelle font au format TTF. Il suffit d'utiliser la fonction imagettftext() à la place de imagestring() en passant le lien vers le fichier.

Par exemple si le fichier "ArialRoundedBold.ttf" est dans le même dossier que le script :


imagettftext($img, 20, 0, 0, 0, imagecolorallocate($img, 0, 0, 0), "ArialRoundedBold.ttf", "Mon texte en Arial Rounded Bold");

En utilisant une police au format TTF il est possible de définir la taille des caractères en pixels ou en points selon la version de la librairie GD installée.

En utilisant une police TTF vous ne pouvez plus utiliser les fonctions imagefontwidth() et imagefontheight() pour calcul la position du texte. Il y a mieux avec la fonction imagettfbbox() qui renvoie un tableau avec les coordonnées du rectangle qui entoure le texte.


$box = imagettfbbox(30, 0, 'ArialRoundedBold', 'Ma typo TTF');

L'image ci-dessous vous montre l'ordre des coordonnées.

rectangle de imagettfbbox() en PHP

Le problème avec la fonction imagettfbbox() c'est qu'elle a tendance à renvoyer des coordonnées négatives et qu'il faut tenir compte de la hauteur de ligne de base (baseline) dans notre calcul.

Je vous conseille de lire mon article pour apprendre comment centrer verticalement du texte avec imagettftext.

La méthode de calcul devient la suivante :


$strY = ($aHeight-(abs($box[1])-abs($box[7])))/2;

code sécurité niveau 3 : captcha niveau 3

Démonstration

Ajouter de l'angle et de la couleurs

Nous allons ajouter deux paramètres supplémentaires à la fonction CaptchaImage() :


function CaptchaImage($aText='', $aPath='', $aWidth=200, $aHeight=50, $aNbLine=0, $aFontSize=20, $aLetterMaxAngle=5){

Maintenant que nous voulons afficher chaque lettre avec un angle et une couleur différente il faut revoir le code qui affiche le texte.


// affiche le texte, lettre par lettre

// enregistre le nombre de lettre
$strLen = strlen($aText);

// boucle à travers toutes les lettres
for($i=0; $i<$strLen; $i++){

	// change la couleur du caractère
	$r = rand(0, 150);
	$v = rand(0, 150);
	$b = rand(0, 150);
	$color = imagecolorallocate($img, $r, $v, $b);
	
	// change un angle aléatoire avec pour limite $aLetterMaxAngle
	$angle = rand(-$aLetterMaxAngle, $aLetterMaxAngle);
	
	// affiche la lettre
	$l = substr($aText, $i, 1);
	imagettftext($img, $aFontSize, $angle, $strX, $strY, $color, $font, $l);
	
	// récupère les coordonnées de cette lettre
	$box = imagettfbbox($aFontSize, 0, $font, $l);
	
	// déplace le point de coordonnée X
	// ajoute un 1/8e de la hauteur de la police
	// sinon les lettres sont collées les unes aux autres
	$strX += $box[4]+$aFontSize/8;
}

code sécurité niveau 4 : captcha niveau 4

Démonstration

Et maintenant ?

Cette seconde partie vous a permis de voir comment améliorer l'image en utilisant une police TTF de votre choix et en ajoutant un peu de couleur à l'ensemble.

Dans la partie suivante je vous montrerais comment finaliser votre code de sécurité en enregistrant une variable de session.

Liens vers les autres parties de cet article

  1. Création d'un code de sécurité
  2. Amélioration du code de sécurité
  3. Vérification

Article précédent : Comment centrer correctement un texte avec imagettftext en PHP ?

Article suivant : Ressource interprétée comme Image mais transférée avec un type MIME text/html

 

Image Viewer