2011/06/06

Clase para realizar captchas en PHP

En algún momento siempre tendremos que realizar la verificación de que el sujeto al otro lado de la pantalla es un humano y no un robot. Por esa razón aparecieron los temido captchas que nos obligan a realizar un proceso de validación de usuario que las máquinas no son capaces de resolver.

La base de funcionamiento es muy sencilla. Se crea una sesión y en ella se guarda el valor que se corresponde con el captcha gráfico de modo que en el proceso de validación de la información se compara el valor de captcha introducido con el almacenado en la sesión. Si no son iguales, no es un humano (o es uno muy torpe).

En este caso, para dibujar el captcha se usa un TTF almacenado en una ruta del servidor especificada en la variable $font_path.

Por supuesto, que esta versión es una muy simplificada y se puede mejorar en todos los aspectos, pero sirve como plantilla para entender cómo funciona todo el proceso.

interface CaptchaInterface{ 
    function setString($string); 
    function getString(); 
    function getImage(); 
    function auth($input); 
} 

// Clase usando Imagick 
class Captcha implements CaptchaInterface{ 
    private $captchaString; 

    public function setString($string){ 
        $this->captchaString = $string; 
    } 

    public function getString(){ 
        return $this->captchaString; 
    } 

    public function getImage(){ 
        $image = new Imagick(); 
        $image->newImage(80,40,'none'); 
        $image->setImageBackgroundColor('#ffffff'); 

        $string = new ImagickDraw(); 
        $string->setFont("fontPath"); 
        $string->setFontSize(14); 
        $string->annotation(0,20,$this->captchaString); 

        $image->drawImage($string); 
        return $image; 

    } 

    public function renderImage($image){ 
        header("Content-type: image/png"); 
        header("Cache-control: no-cache"); 
        $image->setImageFormat("png"); 
        echo $image; 
        exit; 
    } 

    public function auth($input){ 
        return ($this->captchaString == $input)?true:false; 
    } 
} 

//For GD 
class CaptchaGd implements CaptchaInterface{ 
    private $captchaString; 

    public function setString($string){ 
        $this->captchaString = $string; 
    } 

    public function getString(){ 
        return $this->captchaString; 
    } 

    public function getImage(){ 
        $image = imagecreate(80,40); 
        $bcolor = ImageColorAllocate($image, 255, 255, 255); 
        $textcolor = ImageColorAllocate($image, 0,0,0); 
        $font_path="fontPath"; 
        ImageTTFText ($image, 14, 0, 0, 20, $textcolor, 
                $font_path,$this->captchaString); 
        return $image; 

    } 

    public function renderImage($image){ 
        header("Content-type: image/png"); 
        header("Cache-control: no-cache"); 
        $textcolor = ImageColorAllocate($image, 255, 255, 255); 
        ImagePNG($image); 
        ImageColorAllocate($image,$textcolor); 
        imagedestroy($image); 
        exit; 
    } 

    public function auth($input){ 
        return ($this->captchaString == $input)?true:false; 
    } 
}
Para usarlo, lo primero es usar como si fuera una imagen un PHP que usa esta clase dentro del formulario donde se quiera usar el captcha. El PHP de la "imagen" sería:
//CreateCaptchaImage 
session_start(); 
$obj = new Captcha(); 
$_SESSION['captcha']=substr((md5(date("YmdD His"))), 0, 5); 
$obj->setString($_SESSION['captcha']); 
$obj->renderImage($obj->getImage());
Una vez enviados los datos del formulario, el chequeo de la validación del captcha se haría con el siguiente trozo de PHP
//AuthExample(POST Object) 
session_start(); 
$obj = new Captcha(); 
$obj->setString($_SESSION['captcha']); 
if($obj->auth($_POST['captcha']){ 
//True Action 

}else{ 
//False Action 

}

No hay comentarios:

Publicar un comentario