Imágenes de validación de formularios en PHP (captcha).

Imágenes de validación de formularios en PHP (captcha).Este sistema de seguiridad comenzó a hacerse popular cuando los proveedores de cuentas gratuitas de correo vieron que los spammers creaban grandes cantidades de cuentas mediante bots que rellenaban los formularios de manera automatizada. Por ese motivo se hizo necesario crear un sistema que compruebe que quien realiza el registro de la cuenta es una persona y no un programa. Para ello se añadieron imágenes conteniendo un texto aleatorio difícil de leer para una máquina obligando al usuario a introducir ese texto para poder validarse.

Captcha de Hotmail

Voy a exponer un código sencillo en PHP para generar estas imágenes y validarlas en tres capas.

Se requiren conocimientos básicos de manejo de sesiones en php y de la librería gráfica GD.

1 – El script Captcha.php. Una clase que genera la imagen captcha:

<?php
define ("WIDTH", 120);
define ("HEIGHT", 30);
define ("CELL", 20);
define ("FOLDER", "tmp/");
define ("FONTNAME", "AcidDreamer.ttf");
define ("FONTSIZE", 18);
define ("MAXFILES", 5);

class Captcha
{
  function createImage($randString, $name)
  {
    $img = imagecreate(WIDTH, HEIGHT) or die("Can not create image");;
    imagecolorallocate($img, 200, 200, 200);

    //colors
    $black = imagecolorallocate($img, 0, 0, 0);
    imagerectangle($img, 0, 0, WIDTH-1, HEIGHT-1, $black);

    //print letters of rand string
    for ($i=0; $i < strlen($randString); $i++)
    {
      imagettftext($img, FONTSIZE, 10, $i*CELL + 2, 26, $black, FONTNAME, $randString[$i]);
    }
    $imagePath = FOLDER.$name.".png";
    imagepng($img, $imagePath);
    imagedestroy($img);

	return $imagePath;
  }

  function createRandString($numChars)
  {
    $letters = "0123456789";
    $numLetters = strlen($letters);
    $randString = "";
    for ($c=0; $c < $numChars; $c++)
    {
      $num = rand(0, $numLetters-1);
      $randString .= $letters[$num];
    }

	return $randString;
  }

  function deleteOldImages()
  {
    $DIR = opendir(FOLDER);
    $images = array();
    while (($name = readdir($DIR)))
    {
      if ($name != "." && $name != "..")
      {
        $images[] = $name;
      }
    }
    closedir($DIR);
    if (count($images) == 0) return;
    rsort($images);
    while (count($images) > MAXFILES)
    {
      $last = array_pop($images);
      unlink(FOLDER.$last);
    }
  }
}
?>

Se crea una cadena aleatoria para el nombre de la imagen y otra cadena aleatoria para el texto que se mostrará que no coincidirán.
Ambas cadenas se guardan como variables de sesión. Las variables de sesión y su contenido es invisible para el cliente.

2 – El formulario que llama al script anterior ‘formulario.php’:

<?php
session_start(); //iniciamos la sesión

require_once('Captcha.php');
$captcha = new Captcha();
$filename = time()."_".$captcha->createRandString(20);
$_SESSION['image_code'] = $captcha->createRandString(6);
$captcha->deleteOldImages();
?>

<html>
<head></head>
<body>
<form action="validacion.php" method="post">
  <?php
    $_SESSION['image_name'] =
	    $captcha->createImage($_SESSION['image_code'], $filename); ?>
  <img src="<?php echo $_SESSION['image_name'] ?>">
  <input type="text" name="imageText" />
  <input type="submit" name="action" value="Submit" />
</form>
</body>
</html>

3 – La página de validación final ‘validacion.php’:

<?php
session_start(); //iniciamos la sesión
?>
<html>
<body>
<?php
if ($_SESSION['image_code'] == $_POST['imageText'])
{
  //validacion correcta
  echo "Bien";
  session_unregister($_SESSION['image_code']);
  session_unregister($_SESSION['image_name']);
}
else
{
  //ERROR
  echo "error";
}
?>
</body>
</html>

Finalmente, se compara la entrada del usuario con la información guardada en la variable de sesión. Si coincide, se borra la variable de sesión y la imagen y se continúa con la ejecución del script. En caso contrario, se muestra el error y se pide al usuario que vuelva a revisar el formulario.

Unas recomendaciones:

  • El color de fondo y el de la fuente deben ser ligenramente parecidos (negro sobre gris por ejemplo).
  • Usar fuentes poco comunes que estén ligeramente deformadas pero no difíciles de leer.
Sin categoría

Deja un comentario