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.
Afficher les données de l'image
Tout d'abord, nous allons faire un ajustement dans la fonction qui génère le code. Nous n'allons plus enregistrer l'image sur le serveur, mais depuis un cache temporel avec ob_start(); et ob_get_clean().
Il faut remplacer les deux dernières lignes de la fonction CaptchaImage() par le code suivant :
// démarre le cache
ob_start();
// affiche l'image dans le cache
imagepng($img);
// enregistre les données du cache dans une variable et efface le cache
$imgData = ob_get_clean();
// détruit l'image
imagedestroy($img);
// renvoi les données de l'image
return $imgData;
Puisque la fonction renvoie les données brutes au lieu de créer un fichier, on ne peut plus afficher l'image en pointant vers ce fichier. Heureusement il est possible d'afficher des données en HTML en précisant le type. Ici image/png :
<img src="data:image/png;base64,'.base64_encode(CaptchaImage($txt, 'test.png', 200, 50, 20)).'" width="200" height="50" />
Pour info vous pouvez utiliser la même technique en CSS :
.maClasse{
background-image: url(data:image/png;base64, [ici votre image codé en base 64] );
}
Internet Explorer ne supporte pas l'affichage des images avant la version 8.
Les variables de session en PHP avec $_SESSION
Les variables de session sont des variables temporaires affectés à l'utilisateur par le serveur. En PHP elles se manipulent de la même manière que des variables $_POST ou $_GET.
La portée est la même que les variables de cookies, vous pouvez y accéder dans tous les fichiers de votre application, mais elles sont temporaires et ne sont pas enregistrées sur le disque de l'utilisateur.
La durée de ces variables est définie par session_cache_expire(), il faut démarrer ou restaurer une session avec la fonction session_start();.
Par exemple créons un fichier a.php
session_start();
$_SESSION['ma_variable'] = 'Je mange des bretzels au petit déjeuner !';
Vous pouvez créer un fichier b.php et accéder à la variable initialisée dans a.php
session_start();
echo $_SESSION['ma_variable'];
// Je mange des bretzels au petit déjeuner !
Voilà pour les variables de session.
Vérification du code de sécurité
Maintenant que nous avons toutes les cartes en mains pour utiliser un code de sécurité, il est temps de finaliser la vérification.
On vérifie si la variable postée par l'utilisateur n'est pas vide avec empty(). Je préfère empty à isset parce que cette dernière se contente de vérifier l'existence de la variable. Empty vérifie en plus qu'elle n'est pas null ou vide.
On compare ensuite la valeur donnée par l'utilisateur à la valeur enregistrée en session.
- Si les valeurs ne correspondent pas, il suffit d'afficher une information et le formulaire une fois de plus.
- Si les valeurs correspondent, on peut traiter le formulaire. Par mesure de sécurité, on efface tout de même la variable en session.
session_start();
if($_GET['do']=='register'){
if(!empty($_POST['codeSecure']) && $_POST['codeSecure']==$_SESSION['codeSecure']){
// Tout est bon !
$_SESSION['codeSecure'] = '';
}
}
Mise en pratique et test de la session
Voici le fichier complet d'exemple, du PHP un soupçon de CSS un peu d'HTML.
<?php
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;
}
// créer une image avec la bibliothèque GD
function CaptchaImage($aText='', $aWidth=200, $aHeight=50, $aNbLine=0, $aFontSize=20, $aLetterMaxAngle=5){
if(empty($aText)) return 0;
putenv('GDFONTPATH=' .dirname(__FILE__));
$font = 'ArialRoundedBold';
// calcul les coordonnées X et Y pour centrer le texte
$box = imagettfbbox($aFontSize, 0, $font, $aText);
$strX = ($aWidth-abs($box[4]))/2;
$strY = ($aHeight-(abs($box[1])-abs($box[7])))/2;
// créer l'image
$img = imagecreatetruecolor($aWidth, $aHeight);
// ajoute un fond clair
imagefill($img, 0, 0, imagecolorallocate($img, 250, 250, 250));
// active l'anti-aliasing
imageantialias($img, true);
// dessine quelques traits
for($i=0; $i<$aNbLine; $i++){
$r = rand(150, 255);
$v = rand(150, 255);
$b = rand(150, 255);
$color = imagecolorallocate($img, $r, $v, $b);
imageline($img, 0, rand(-50, $aHeight+50), $aWidth, rand(-50, $aHeight+50), $color);
}
// affiche le texte, lettre par lettre
$strLen = strlen($aText);
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 l'angle
$angle = rand(-$aLetterMaxAngle, $aLetterMaxAngle);
imagettftext($img, $aFontSize, $angle, $strX, $strY, $color, $font, substr($aText, $i, 1));
$box = imagettfbbox($aFontSize, 0, $font, substr($aText, $i, 1));
$strX += $box[4]+$aFontSize/8;
}
// démarre le cache
ob_start();
// afiche l'image dans le cache
imagepng($img);
// enregistre les données du cache dans une variable
$imgData = ob_get_clean();
// détruit l'image
imagedestroy($img);
// renvoi la variable
return $imgData;
}
// démarre la session
session_start();
// variable pour savoir si le formulaire a été envoyé
$codeSend = 0;
// variable pour savoir si le code est correct
$codeOk = 0;
if($_GET['do']=='register'){
// l'utilisateur a posté le formulaire
// on initialise la variable $codeSend
$codeSend = 1;
// On vérifie si la variable 'codeSecure' n'est pas vide
// ET si elle correspond avec la valeur enregistré en session
if(!empty($_POST['codeSecure']) && $_POST['codeSecure']==$_SESSION['codeSecure']){
// le code est bon, on peut traiter le formulaire normalement
$codeOk = 1;
// réinitialise la variable en session par sécurité
$_SESSION['codeSecure'] = '';
}
}
if($codeOk){
// le code est correct
$h = '<div class="codeOk"><h1>Code correct !</h1><p><a href="code-securite-php-final.php">Recommencer</a></p></div>';
}else{
// affiche le formulaire
if($codeSend){
// l'utilisateur a envoyé le formulaire, mais le code est incorrect
$h = '<div class="codeErreur"><h1>Code incorrect !</h1><p>Le code ne correspond pas</p></div>';
}
$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);
// enregistre le code dans une variable de session
$_SESSION["codeSecure"] = $txt;
// formulaire
$h .= '
<div id="main">
<h1>Test de code de sécurité en PHP</h1>
<form method="post" action="code-securite-php-final.php?do=register">
<p>Placez les champs de votre formulaire ici...</p>
<h2>Code de sécurité</h2>
<p>On ajoute le code de sécurité à la fin</p>
<p><span class="formMarge"> </span><img src="data:image/png;base64,'.base64_encode(CaptchaImage($txt, 200, 50, 20)).'" width="200" height="50" alt="" /></p>
<p><label class="formMarge">Code : </label><input type="text" value="" name="codeSecure" id="champ_codeSecure" size="30" maxlength="50"></p>
<p><span class="formMarge"> </span><input type="submit" name="Submit" value="Tester le code"></p>
</form>
</div>';
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Code de sécurité</title>
<style type="text/css">
body{
margin: 0;
padding: 0;
background-color: #f8f4ee;
text-align: center;
font-family: Helvetica, serif;
font-size: 14px;
}
#main{
margin: 0 20%;
text-align: left;
}
h1{
margin: 0;
padding: 1em 0 0.5em 0;
font-size: 2em;
}
.codeOk, .codeErreur{
padding: 5% 10%;
margin: 5% 10%;
border: 0.5em dashed #f8f4ee;
text-align: center;
}
.codeOk{
background-color: #ccff66;
}
.codeOk a{
color: #000;
text-decoration: none;
border-bottom: 1px dotted #000;
}
.codeErreur{
background-color: #ff8485;
}
</style>
</head>
<body>
<?php
echo $h;
?>
</body>
</html>