PHP - Combattre le flood

Par FlUxIuS 2008-05-09 { Catégorie : PHP }

Depuis quelques temps vous observez sur votre blog plus de spams que de commentaires ou même une tonne de posts ayant le même contenu "flood" . Ne sachant plus quoi faire, certains stoppent la mise de commentaires, d'autres continuent à les supprimer un par un... Mais celà ne s'applique pas qu'aux blogs et touche aussi l'envoi d'email. Comment faire pour continuer à recevoir des messages et être à l'abris de ces parasites ?

Nous vous donnerons les solutions php dans cet article :)

 

C'est là où on vois que la publicité représente plus de la moitié et on peut constater qu'elle est plus élevée dans notre toile qu'est internet...

Vous me direz peut être que celà n'a rien à voir avec le sujet mais c'est une prise de conscience à avoir lorsque vous diffusez par votre site proposant aux utilisateurs l'échange de commentaires ou emails.

N'avez-vous jamais été tentés de flooder sur un site web, un chat irc ... ? Rien que pour faire de la publicité... Mais sans doutes, vos outils ne sont pas aussi puissants que les prédateurs d'aujourd'hui ... Nous allons donc débuter en vous présentant le principe du Captcha pour vérifier la présence de robots...

 

Le captcha - Je t'ai vu Robot !

Introduction

De plus en plus d'utilisateurs souhaitant faire de la publicité ou énerver un webmaster, utilisent des sortes de robots et de plus en intélligents. Intelligents car ils ont la possibilité de détecter certains tags et même d'effectuer des calculs si besoin est.

C'est donc pour celà que certains utilisateurs ont pensé à user du principe du Captcha pour distinguer l'humain de l'ordinateur "Verification of a human in the loop, or Identification via the Turing Test".

Installation du Captcha

La class

Avant tout, il est utile d'avoir la librairie GD2 installé avant d'utiliser la Class.

Pour cette article nous utiliseront  captcha (Disponible ici) :

<?php 
 
class captcha {
 
    private $randString = '';
    private $stringLength = 10;
    private $imageWidth = false;
    private $imageHeight = false;
    private $background = true;
    private $backgroundColor = array('R'=>255, 'V'=>255, 'B'=>255);
    private $borderColor = array('R'=>226, 'V'=>113, 'B'=>59);
    private $borderWidth = 0;
    private $textColor = array('R'=>0, 'V'=>0, 'B'=>0);
    private $forbiddenChars= array(1,0,'l','0');
    private $font = '';
    private $fontSize = 15;
    private $fromBorder = 10;
    private $type = '';
    private $shadow = false;
    private $shadowColor = array('R'=>128, 'V'=>128, 'B'=>128);
    private $shadowX = 2;
    private $shadowY = 2;
    private $backgroundImage = false;
    private $textAngle = 0;
    private $roundedCorners = false;
    private $roundedCornersRadius = 5;
 
    /**
* Constructeur - fixe le type d'image : PNG,GIF,JPEG
*
* @param string $type type de l'image
*/
public function __construct($type='PNG') { $this->setImageType($type); }   /**
* Fixe la longueur de la chaîne aléatoire générée
*
* @param int $lenght longueur de la chaîne
*/
public function setStringLenght($lenght) { $this->stringLength = $lenght; }   /**
* Fixe la couleur de fond de l'image
*
* @param int $R rouge
* @param int $V vert
* @param int $B bleu
*/
public function setBackgroundColor($R,$V,$B) { $this->backgroundColor['R'] = $R; $this->backgroundColor['V'] = $V; $this->backgroundColor['B'] = $B; }   /**
* Fixe la couleur de la bordure
*
* @param int $R rouge
* @param int $V vert
* @param int $B bleu
*/
public function setBorderColor($R,$V,$B) { $this->borderColor['R'] = $R; $this->borderColor['V'] = $V; $this->borderColor['B'] = $B; }   /**
* Fixe la taille de la bordure
*
* @param int $width taille en pixel de la bordure
*/
public function setBorderWidth($width) { $this->borderWidth = (int)$width; }   /**
* Fixe la couleur du texte
*
* @param int $R rouge
* @param int $V vert
* @param int $B bleu
*/
public function setTextColor($R,$V,$B) { $this->textColor['R'] = $R; $this->textColor['V'] = $V; $this->textColor['B'] = $B; }   /**
* Fixe la largeur de l'image
*
* @param int $width largeur en pixel de l'image
*/
public function setImageWidth($width) { $this->imageWidth = $width; }   /**
* Fixe la hauteur de l'image
*
* @param int $height hauteur en pixel de l'image
*/
public function setImageHeight($height) { $this->imageHeight = $height; }   /**
* Fixe la police True Type et sa taille
*
* @param string $font chemin vers la police
* @param int $size taille de la police
*/
public function setFont($font, $size) { if(!is_readable($font)) { throw new Exception('La police est introuvable'); } $this->font = $font; $this->fontSize = $size; }   /**
* Fixe si une ombre doit être appliquée au texte
*
* @param int $x décalage de l'ombre en absisse
* @param int $y décalage de l'ombre en ordonné
*/
public function setShadow($x=false,$y=false) { $this->shadow = true; if($x) { $this->shadowX = (int)$x; } if($y) { $this->shadowY = (int)$y; } }   /**
* Fixe la couleur de l'ombre
*
* @param int $R rouge
* @param int $V vert
* @param int $B bleu
*/
public function setShadowColor($R,$V,$B) { $this->shadow = true; $this->shadowColor['R'] = $R; $this->shadowColor['V'] = $V; $this->shadowColor['B'] = $B; }     /**
* Définie si une image de fond doit être appliquée
*
* @param string $image chemin vers l'image
*/
public function setBackgroundImage($image) { if(!is_readable($image)) { throw new Exception('Image de fond introuvable'); } $this->backgroundImage = $image; }   /**
* Fixe l'angle du texte
*
* @param int $angle angle en degrés
*/
public function setTextAngle($angle) { $this->textAngle = (int)$angle; }   /**
* Fixe la taille de la marge par rapport à la bordure
*
* @param int $margin taille en pixel de la marge
*/
public function setMarginFromBorder($margin) { $this->fromBorder = (int)$margin; }   public function setRoundedCorners($radius=false) { $this->roundedCorners = true; if($radius) { $this->roundedCornersRadius = (int)$radius; } }     /**
* Construit l'image
*
*/
public function getImage() { if(!$this->font) { throw new Exception('Il faut charger une police'); }   $text = $this->getRandString(); $text = trim(preg_replace('`(\w)`', '$1 ', $text)); $box = imagettfbbox($this->fontSize,$this->textAngle,$this->font,$text);   if(!$this->imageHeight) { $boxHeight = max($box[1],$box[3]) - min($box[7],$box[5]); $this->imageHeight = $boxHeight + $this->borderWidth*2 + $this->fromBorder*2; } if(!$this->imageWidth) { $boxWidth = max($box[4],$box[2]) - min($box[6],$box[0]); $this->imageWidth = $boxWidth + $this->borderWidth*2 + $this->fromBorder*2; }   if(function_exists('imagecreatetruecolor')) { $im = imagecreatetruecolor($this->imageWidth, $this->imageHeight); } else { $im = imagecreate($this->imageWidth, $this->imageHeight); } // border if($this->borderWidth > 0) { $border = imagecolorallocate( $im, $this->borderColor['R'], $this->borderColor['V'], $this->borderColor['B'] ); if(!$this->roundedCorners) { imagefilledrectangle( $im, 0, 0, $this->imageWidth, $this->imageHeight, $border ); } else { $this->ImageRectangleWithRoundedCorners( $im, 0, 0, $this->imageWidth, $this->imageHeight, $border, $this->roundedCornersRadius ); } }   // background $background = imagecolorallocate( $im, $this->backgroundColor['R'], $this->backgroundColor['V'], $this->backgroundColor['B'] ); imagefilledrectangle( $im, $this->borderWidth, $this->borderWidth, $this->imageWidth-$this->borderWidth, $this->imageHeight-$this->borderWidth, $background );   if($this->backgroundImage) { // Calcul des nouvelles dimensions list($width, $height,$type) = getimagesize($this->backgroundImage);   $new_width = $this->imageWidth-$this->borderWidth*2; $new_height = $this->imageHeight-$this->borderWidth*2;   if($type === 1) { $type_ = 'gif'; } elseif($type === 2) { $type_ = 'jpeg'; } elseif($type === 3) { $type_ = 'png'; } else { throw new Exception('Mauvais type pour l\'image de fond'); } $fct = 'imagecreatefrom' . $type_; $imb = $fct($this->backgroundImage);     imagecopyresampled( $im, $imb, $this->borderWidth, $this->borderWidth, 0, 0, $new_width, $new_height, $width, $height );   imagedestroy($imb); }   // couleur du texte $textColor = imagecolorallocate ( $im, $this->textColor['R'], $this->textColor['V'], $this->textColor['B'] );   // centrage horizontal $x = ($this->imageWidth - $boxWidth)/2; // centrage vertical $y = $this->imageHeight - $this->borderWidth - $this->fromBorder;   // ombre if($this->shadow) { $shadow = imagecolorallocate( $im, $this->shadowColor['R'], $this->shadowColor['V'], $this->shadowColor['B'] ); imagettftext( $im, $this->fontSize, $this->textAngle, $x+$this->shadowX, $y+$this->shadowY, $shadow, $this->font, $text ); }   // le texte imagettftext( $im, $this->fontSize, $this->textAngle, $x, $y, $textColor, $this->font, $text );   $this->makeHeaders(); $image_function = 'image' . $this->type; $image_function($im); imagedestroy($im); }     /**
* Récupère la chaîne aléatoire générée
*
* @return string chaîne aléatoire générée
*/
public function getRandString() { if(!$this->randString) { $T = array_merge(range('a','z') , range('A', 'Z') , range(1,9)); shuffle($T); //$TT = array_filter($T, array($this, 'forbiddenCharsFilter')); $TT = array_chunk($T, $this->stringLength);   $this->randString = implode('', $TT[0]); } return $this->randString; }   private function ImageRectangleWithRoundedCorners(&$im, $x1, $y1, $x2, $y2, $color, $radius) { // transparence $trans = imageColorAllocate ($im, 255, 255, 255); $color_ = imagecolortransparent($im, $trans); // rectangle sans coins imagefilledrectangle($im, $x1, $y1, $x2, $y2, $color_); imagefilledrectangle($im, $x1+$radius, $y1, $x2-$radius, $y2, $color); imagefilledrectangle($im, $x1, $y1+$radius, $x2, $y2-$radius, $color); // coins arrondis imagefilledellipse($im, $x1+$radius, $y1+$radius, $radius*2, $radius*2, $color); imagefilledellipse($im, $x2-$radius, $y1+$radius, $radius*2, $radius*2, $color); imagefilledellipse($im, $x1+$radius, $y2-$radius, $radius*2, $radius*2, $color); imagefilledellipse($im, $x2-$radius, $y2-$radius, $radius*2, $radius*2, $color);   }   private function forbiddenCharsFilter($in) { return in_array($in, $this->forbiddenChars); }   private function setImageType($type) { switch(strtolower($type)) { case 'gif' : case 'png' : case 'jpeg' : $this->type = $type; break; case 'jpg' : $this->type = 'jpeg'; break; default : $this->type = 'png'; } if(!function_exists('image'.$this->type)) { throw new Exception('La fonction n\'est pas disponible'); } }   private function makeHeaders() { header('Expires: Mon, 01 Jan 2000 00:00:00 GMT'); header('Last-Modified: ' . gmdate("D, d M Y H:i:s") . ' GMT'); header('Cache-Control: no-store, no-cache, must-revalidate'); header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); header('Content-Type: image/' . $this->type); } } ?>

La class est simple d'installation, il suffit de l'enregistrer sous l'extension ".php".

Exemple d'utilisation

<?php
 
include_once 'captcha.class.php';
 
/*
* Image : JPEG, GIF, PNG ...
*/
$I = new captcha('GIF');   // on génère une chaine aléatoire de 5 caractères $I->setStringLenght(5);   // police KATZCK__.TTF de taille 15 $I->setFont('fonts/KATZCK__.TTF' , 35);   // Verte de 5 px $I->setBorderColor(0,121,21); $I->setBorderWidth(5); // Ombre porte $I->setShadow(); // couleur de fond Vert $I->setBackgroundColor(100,200,100); $I->setRoundedCorners(10); $I->setTextAngle(5); // génération de l image $I->getImage();   // on met la chaîne générée en session pour le contrôle $_SESSION['captcha-control'] = $I->getRandString(); ?>

Voilà un exemple d'utilisation du Captcha mais cette class est assez limitée afin rendre le texte illisible pour les robots, je vous conseil donc d'utiliser par exemple HN captcha.

Conseils supplémentaires : utilisez aussi les images de fond pour tromper les robots (comme je l'ai dit les robots deviennent de plus en plus intelligents).

Phase critique

Le captcha est très désavantageux pour ceux qui auraient des problèmes de vue. Mais celà protége déjà d'une tonne de flood que l'on aurait à supprimer dans la journée...

A suivre : Combattre le spam

Powered by SlashOn blog - © Sebastien D. (FlUxIuS)

Debian powered Server Creative Commons License W3c Validation
Cette création est mise à disposition sous un contrat Creative Commons