Cómo hemos ido comentando desde hace buen tiempo atrás, existen varios métodos para bloquear el spam de nuestras páginas web; por ejemplo, uno de los métodos que más agrada es utilizando Akismet, un servicio web anti spam, transparente al usuario.
Sin embargo, hay veces que Akismet no cubre las expectativas ó simplemente, hay aplicaciones en que no puede utilizarse. Por ello, vamos comentar otro método para impedir el acceso de los robots a nuestro sistema, esta vez, con la creación de un Captcha con PHP.
Esta es la traducción de un artículo recientemente publicado en fuzzyopinions, del cual, su simpleza y funcionamiento y diseño final me han agradado bastante. El resultado final del Captcha lo pueden observar en la siguiente imagen:
Cómo sabrán un captcha es solicitar al usuario que escriba los caracteres que aparecen en una imagen dentro de un campo de texto. Si lo hace correctamente tendrá acceso, de lo contrario, se le pedirá que vuelva a escribir el código, indicándole que lo que ha escrito esta errado.
7 pasos para crear un captcha
Estos son los siete pasos básicos para generar un sistema Captcha:
- Generar un código aleatorio
- Añadir el código a una cookie, variable de sesión ó base de datos que será recuperada desde la siguente página
- Escribir el texto dentro de una imagen
- Mostrar la imagen al usuario que quiera acceder al recurso
- Proveer de un formulario, donde el usuario ingrese el código y lo envíe
- Verificar el código de la clave enviada (en el paso 2)
- Si el código es correcto, se permite el acceso
A continuación veremos el código necesario para crear nuestro captcha.
Generando y almacenando el código
Cómo mencionamos en el primer paso, el texto del código debe ser aleatorio. Hay varias maneras de conseguir esto, por lo que en este paso podemos sentirnos libres de experimentar, pero eso si, lo que hagamos debe de cumplir dos cosas: 1) Recuperar un valor que cambie constantemente y 2) Cifrar ese valor.
Un valor que cambia constantemente puede ser, por ejemplo, la fecha y hora del servidor, para ello, nos serviremos de las funciones microtime( ) y mktime( ) de PHP. Una vez con el valor totalmente aleatorio en nuestras manos, lo cifraremos con la función md5() de PHP. Finalmente (fíjense en la última línea del código), almacenaremos el valor en una variable de sesión.
<?php
// Iniciamos sesión
session_start( );
// Indicamos el tamaño de nuestro captcha, puede ser aleatorio para mayor seguridad
$captchaTextSize = 7;
do {
// Generamos un string aleatorio y lo encriptamos con md5
$md5Hash = md5( microtime( ) * mktime( ) );
// Eliminamos cualquier caracter extraño
preg_replace( ‘([1aeilou0])’, “”, $md5Hash );
} while( strlen( $md5Hash ) < $captchaTextSize );
// necesitamos sólo 7 caracteres para este captcha
$key = substr( $md5Hash, 0, $captchaTextSize );
// Guardamos la clave en la variable de sesión. La clave esta encriptada.
$_SESSION[’key’] = md5( $key );
?>
Mostrando el código aleatorio en la imagen Captcha
Una vez generado el código captcha y almacenado correctamente, procederemos a recuperarlo y mostrarlo al usuario. Para el manejo de la imagen utilizaremos la librería GD.
<?php
// almacenamos la imagen base, el background.
$captchaImage = imagecreatefrompng( “images/captcha.png” );
/*
Seleccionamos un color de texto. Cómo nuestro fondo es un verde agua, escogeremos un cólor verde para el texto. El color del texto es, preferentemente, el mismo que el del background, aunque un poco más oscuro para poder distnguirlo.
*/
$textColor = imagecolorallocate( $captchaImage, 31, 118, 92 );
/*
Seleccionamos un color para las líneas que queremos se dibujen en nuestro captcha. En este caso usaremos una mezcla entre verde y azul
*/
$lineColor = imagecolorallocate( $captchaImage, 15, 103, 103 );
?>
Ya hemos seleccionado los colores, ahora queremos mostrar algunas líneas que incrementen la dificultad, para que los robots (spam) no lean nuestro código (texto aleatorio).
<?php
// recuperamos el parametro tamaño de imagen
$imageInfo = getimagesize( “images/captcha.png” );
// decidimos cuantas líneas queremos dibujar
$linesToDraw = 10;
// Añadimos las líneas de manera aleatoria
for( $i = 0; $i < $linesToDraw; $i++ ) {
// utilizamos la función mt_rand()
$xStart = mt_rand( 0, $imageInfo[ 0 ] );
$xEnd = mt_rand( 0, $imageInfo[ 0 ] );
// Dibujamos la linea en el captcha
imageline( $captchaImage, $xStart, 0, $xEnd, $imageInfo[1], $lineColor );
}
?>
Finalmente, escribimos nuestro código en la imagen y la mostramos en la pantalla. Comenzaremos con una imagen de fondo pre generada. Este método, puede fácilmente permitirnos incluir docenas de fondos adicionales, seleccionados al azar, o aún, para hacerlo más complejo, podríamos generarlo nosotros mismos, dentro del captcha.
Para escribir nuestro captcha usaremos la función imagettftext(), la cual se caracteriza por escribir un texto sobre una imagen usando fuentes TrueType. En este caso, utilizaremos la fuente BitStream Vera Sans Bold, que es una fuente Open Source que podemos copiar y redistribuir libremente. Ahora bien, si queremos podemos utilizar cualquier otra fuente, ó aún mejor, mezclar fuentes al azar para hacer más difícil que los robots lean nuestra imagen.
<?php
/*
Escribimos nuestro string aleatoriamente, utilizando una fuente true type. En este caso, estamos utilizando BitStream Vera Sans Bold, pero podemos utilizar cualquier otra.
*/
imagettftext( $captchaImage, 20, 0, 35, 35, $textColor, “fonts/VeraBd.ttf”, $key );
/*
Mostramos nuestra imagen. Preparamos las cabeceras de la imagen previniendo que no se almacenen en la cache del navegado
*/
header ( “Content-type: image/png” );
header(”Cache-Control: no-cache, must-revalidate”);
header(”Expires: Fri, 19 Jan 1994 05:00:00 GMT”);
header(”Pragma: no-cache”);
imagepng( $captchaImage );
?>
Ahora que ya tenemos nuestro captcha elaborado, el paso final es crear el formulario que interactúe con el usuario.
Incluyendo el Captcha en la página web
Para verificar el correcto funcionamiento de nuestro captcha, necesitamos crear un formulario que permita al usuario ver el código, escribirlo en un campo de texto y enviarlo pulsando un botón. Esto ya todos lo debemos de conocer, por lo que no nos explayamos en este punto.
<img src=”captcha.php” border=”0″ />
<form name=”captcha-form” method=”POST” action=”captcha-verify.php”>
<input type=”text” name=”code” width=”25″ />
<input type=”submit” name=”submit” value=”submit” />
</form>
Ahora bien, asumiendo que el formulario ha sido enviado, deberemos ser capaces de verificar el código enviado. Por ejemplo podemos utilizar un script PHP similar a este.
<?php
session_start( ); // iniciamos sesión
/*
Encriptamos la clave pasada por el formulario y luego la comparamos con el valor del captcha (almacenado en la variable de sesión)
*/
if( md5( $_POST[ ‘code’ ] ) != $_SESSION[ ‘key’ ] ) {
echo “Usted no ha escrito el código de verificación correctamente. Por favor, intentelo de nuevo!”;
} else {
echo "Usted ha escrito el código correctamente. Bienvenido...";
}
?>
Eso es todo. Desde luego, hay mucho que se podría hacer para personalizar un Sistema Captcha, hacerlo más complejo e incluirlo en nuestros sitios web. Estas son algunas ideas:
- Combinar palabras para hacerlo semilegible y dificultar a los robots que lean la imagen. Esto se podría hacer utilizando dos archivos de donde se recuperen los textos.
- Girar el texto al azar y jugar con el espacio entre las letras. Aunque hay que tener cuidado de no hacerlo muy enrevesado, tanto que nuestros propios usuarios no puedan entenderlo.
- Cambie la ubicación del texto en la pantalla. En nuestro caso, el texto siempre aparece en un mismo punto, pero podríamos cambiar su ubicación al azar.
Espero que este mini tutorial sobre la creación de un Sistema Captcha con PHP les haya sido de ayuda, aunque sea mostrando los conceptos básicos de su creación.
Ejemplo | Resultado Final
Descargar | Código Fuente
Muy buen tutorial gracias!
Gracias. coloque el captcha en mi webside, pero entonces el captcha se toma todo los atributos y deja de funcionar la conexcion a la base de datos en el servidor, que debo hace para corregir el error.
Muchisimas gracias esta genial, me salvaste la vida!!!
Yo utilizaria lo siguiente y mas facil y sin tantos recursos :P
<?php session_start();
//GENERADOR DE CAPTCHA
function random_text($tamaño){
$fuente = "1234567890abcdefghijklmnopqrstuvwxyz";
$return = substr(str_shuffle($fuente),0,$tamaño);
return $return;
}
$_SESSION['captcha'] = random_text(8);
ob_clean(); //Limpiar Buffer
//CREAR IMAGEN CON TEXTO INGRESADO!
$captcha = imagecreatefromgif("captcha.gif");
$color = imagecolorallocate($captcha,0,0,0); //0 XQ YA TENGO IMAGEN DE FONDO xD!
imagestring($captcha,5,15,5,$_SESSION['captcha'],$color);
header("Content-type: image/gif ");
//Terminar Imagen
imagegif($captcha);
imagedestroy($captcha);
?>
Excelente trabajo amigo.
No me llegan los correo, no se que estoy haciendo mal, lo tengo así:
echo “Usted no ha escrito el código de verificación correctamente. Por favor, intentelo de nuevo!”;
} else {
echo "Mensaje enviado satisfactoriamente";
$nombre = $_POST['nombre'];
$mail = $_POST['mail'];
$motivo = $_POST['motivo'];
$otro_motivo = $_POST['otro_motivo'];
$mensaje = $_POST['mensaje'];
$asunto = "Formulario de Contacto de Multitrans";
$header = 'From: ' . $mail . " \r\n";
$header .= "X-Mailer: PHP/" . phpversion() . " \r\n";
$header .= "Mime-Version: 1.0 \r\n";
$header .= "Content-Type: text/plain";
$mensaje = "
-----------Informacion del Usuario-----------
Nombre del Usuario:___= ".$nombre."
Email:________________= ".$mail."
Motivo:_______________= ".$motivo."".$otro_motivo."
Mensaje:_______________________= ".$mensaje."
";
$para = "MI CORREO";
mail($para, $asunto, $mensaje, "From: ".$mail);
}
?>
Necestio ayuda urgente... alguien me podría decir como hago para que mi formulario me llegue a mi correo..?
Gracias
Hola,
lo primero es felicitarte por el tutorial, es justo lo que estaba buscando.
A pesar de ello, a mi también me daba un error al actualizar la página del formulario (por ejemplo cuando se introducía mal el código y volvía hacia atrás): los caracteres de la imagen se disparaban, en lugar de salir los 7 que deberían.
Personalmente, creo haber subsanado el error mediante una finalización de la variable sesión ("session_destroy()") al final de la página de verificación.
No sé si será la solución ideal, pero de momento me ha funcionado :-P
Saludos y gracias por el tutorial.
Gracias por el tutorial, me ha sido de mucho utilidad... Gracias!
tengo un problema con el catpcha, cada ves que genero otro codigo me sale varios letras, solamente me tendria que salir 7 caracteres, pero me salen demasiados hasta que no se puede ver en el cuadro del captcha
hola amigos me baje el zip del ejemplo y al momento de verlo en mi pc, no puedo ver la imagen, creo q es por la libreria GD, como hago para instalarlo o que se hace. atte
En todo este procedimiento, donde va insertada MI DIRECCION DE MAIL?
Porque mi formulario normal el action es form action="/cgi-bin/FormMail.cgi" method="post" y procesa al destinatario como input type=hidden name="recipient" value="informes@empanadascriollas.com.ar" pero con el que baje de la web, el form action="verificar.php" method="POST" como sabe a que direccion debe enviar el formulario?
Excelente lo tuyo, ya lo estoy implementando...
saludos.....
crear un weblog es mi trabajo de programacion de fin de ciclo esto creo que me va ha ayudar y aun necesito mas ayuda para hacerlo lo mejor que pueda
hola,revisé el tutorial me funcion
Ha sido de gran ayuda
Funciona bien,pero a mi me da un problema que aunque pongan el codigo mal lo sige enviando el formulario de correo Un saludo
En una web me funcionaba bien pero luego lo probe en otra y hac
podrias renombrar la variable local $key a $key2 por ejemplo y asi ya no tendr
Muy buen tutorial.He detectado un pequeño error, pero no veo como solucionarlo.Si definimos $captchaTextSize = 7se supone que la longitud de la cadena deber
por si no sabias a
Estoy usando esta tecnolog
Soy MUY NOVATO :/
En este proceso, donde va insertada MI DIRECCION DE MAIL?
Porque mi formulario normal el action es y procesa al destinatario como pero con este codigo,
como sabe a que direccion debe enviar el formulario?
Gracias!
El ejemplo tienes que adaptarlo a tu formulario y luego de procesar el captcha, recuperar cada uno de los valores que se envía por post, antes de realizar la consulta a la BD.
gracias Baluart, podrias darme un ejemplo de los cambios que debo hacer y enviarmelo a mi correo investfxbank@gmail.com Mucho te lo agradeceria, porque hacerlo por ensayo y error, es muy pesado
Gracias de nuevo
podrias enviarme un ejemplo de como recuperar los post, para que el formulario se conecte a la base de datos... Te lo agradezco
Alfredo, fijate arriba en el comentario de tucuta, esa es la manera de recuperar las variables pasadas de un formulario con POST
$nombre = $_POST['nombre'];
$_POST['nombre'] hace referencia al valor del atributo name de un campo de texto:
< input type="text" name="nombre" value=""/>
Esto es todo lo que necesitas saber para recuperar los valores del formulario y pasarlos a la BD, luego de pasar el captcha.
Saludos.
MIRA ESTOY INTENTANDO MUNTAR EL CAPTCHA A MI BLOGGER Y NO LO HE LOGRADO ME PODRIAS AYUDAR NO SE COMO HACERLO ES MI NOTA FINAL Y TENGO QUE PRESENTARLO
Muchas gracias, es un buen material, había probado muchos pero no explicaban detalladamente como aplicarle un formato personalizable al captcha, muy útil, me ha sido de ayuda.