jueves, 5 de junio de 2014

Crear una imagen captcha para la validación de formularios


Bienvenid@s, hoy crearemos una imagen captcha con PHP para incluirla en nuestros formularios y así dar mayor seguridad a la aplicación, con esto podemos evitar que robots maliciosos puedan ejecutar los formularios de forma automática. 

La imagen captcha será creada con PHP y la librería de funciones GD, esta librería proporciona una serie de herramientas muy útiles para generar casi cualquier tipo de imagen, para el ejemplo la imagen será del tipo PNG.

La imagen captcha contendrá un número aleatorio que generaremos a través de una función llamada generate_captcha($chars, $length), en el parámetro $chars incluiremos un array con los caracteres que queremos que compongan el código captcha por ejemplo ... array('a', 'e', 'i', 'o', 'u') entonces generará un código aleatorio con las letras 'aeiou', el segundo parámetro $length es para definir la longitud del código captcha, por ejemplo ... generate_captcha(array('a', 'e', 'i', 'o', 'u'), 4) puede regresarnos ... oieu ..., uaee .... 

El código captcha también será guardado encriptado con sha1 en una cookie llamada 'captcha', que posteriormente podremos acceder a su valor para comprobar si el usuario ha ingresado correctamente o no el código captcha.

En el ejemplo intervienen:

captcha.php : Donde se crear la imagen captcha

index.php : Este archivo contiene un formulario con la imagen captcha y dos campos email y captcha, que podrá ser enviado mediante jQuery AJAX.

ajax.php : Este archivo recibe los parámetros del formulario y validará si el valor del campo captcha es correcto al ser comparado con la cookie 'captcha'.

Al final de este artículo pueden ver el vídeo explicativo.


captcha.php

<?php 
header("Content-Type: image/png");
$im = imagecreate(45, 23) or die("Ha ocurrido un error, librería de funciones GD no disponible");
$color_fondo = imagecolorallocate($im, 0, 0, 0);
$color_texto = imagecolorallocate($im, 255, 255, 255);
function generate_captcha($chars, $length)
{
$captcha = null;
for ($x = 0; $x < $length; $x++)
{
$rand = rand(0, count($chars)-1);
$captcha .= $chars[$rand];
}
return $captcha;
}
$captcha = generate_captcha(array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f'), 4); /* 4 es la longitud del capcha */
setcookie('captcha', sha1($captcha), time()+60*3);
imagestring($im, 5, 5, 5,  $captcha, $color_texto);
imagepng($im);


index.php

<!DOCTYPE HTML>
<html>
 <head>
  <script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
       <script>
     $(function(){
        $("#btn").on("click", function(){
            var formData = $("#formulario").serialize();
            var ruta = "ajax.php";
            $.ajax({
                url: ruta,
                type: "POST",
                data: formData,
                success: function(datos)
                {
                    $("#respuesta").html(datos);
                }
            });
        });
  
  $("#actualizar_captcha").on("click", function(){
           document.location.reload();
    });
     });
    </script>
 </head>
 <body>
<div id="respuesta"></div>
<form method="POST" id="formulario">
<table>
<tr>
<td>Email:</td><td><input type="email" id="email" name="email"></td>
</tr>
<tr>
<td>Captcha:</td><td><input type="text" id="captcha" name="captcha"></td>
</tr>
<tr><td></td><td><img src="captcha.php"><button id="actualizar_captcha" type="button">Actualizar</button></td></tr>
</table>
<button id="btn" type="button">Enviar</button>
</form>
 </body>
</html>


ajax.php

<?php 
if (isset($_POST))
{
$email = $_POST["email"];
$captcha = sha1($_POST["captcha"]);
$numero_captcha = $_COOKIE["captcha"];
if (!preg_match("/^[a-zA-Z0-9\._-]+@[a-zA-Z0-9-]{2,}[.][a-zA-Z]{2,4}$/", $email))
{
echo "<p style='color: red'>El formato de email es incorrecto</p>";
}
else if ($captcha != $numero_captcha)
{
echo "<p style='color: red'>El Captcha no coincide</p>";
}
else
{
//LAS ACCIONES CORRECTAS
echo "<p style='color: blue'>Acción llevada a cabo correctamente</p>";
/*Eliminamos la cookie*/
setcookie("captcha", "", -1);
?>
<script>
/*Restauramos el formulario y el captcha*/
document.getElementById("formulario").reset();
document.location.reload();
</script>
<?php
}
}
?>