Crear CAPTCHA con PHP

  • 17/08/2007
  • 9:52 am
  • unijimpe

Captcha es una palabra aleatoria y en ocasiones distorsionada mostrada como imagen que se utiliza para evitar que los robots accedan a determinadas web. Este tipo de verificación es utilizada por los programadores para evitar el spam en lo blogs por ejemplo.

captcha.gif

La idea básica para crear un Captcha es generar primero un texto aleatorio, luego basado en este texto generamos una imagen la cual se muestra al usuario, finalmente se compara el texto ingresado por el usuario con la palabra aleatorio generada.

Generar el Captcha
La primero es crear una imagen con un texto aleatorio, para ello un archivo llamado captcha.php el cual creará dinámicamente el texto. Para ello creamos una función llamada randomText que se encarga de generar una cadena de texto aleatorio, acepta un parámetro el cual le indica cuantos caracteres puede tener el texto generado.

PHP:
  1. // archivo: captcha.php
  2. function randomText($length) {
  3.     $pattern = "1234567890abcdefghijklmnopqrstuvwxyz";
  4.     for($i=0;$i<$length;$i++) {
  5.       $key .= $pattern{rand(0,35)};
  6.     }
  7.     return $key;
  8. }

Lo siguiente es crear una variable de sesión para guardar el texto generado, luego de ello tomamos una imagen que contiene el fondo para el captcha en nuestro caso la imagen es bgcaptcha.gif, luego creamos el texto sobre esta imagen para luego mostrarla en el navegador como imagen enviándole un header indicando el tipo de archivo.

PHP:
  1. $_SESSION['tmptxt'] = randomText(8);
  2. $captcha = imagecreatefromgif("bgcaptcha.gif");
  3. $colText = imagecolorallocate($captcha, 0, 0, 0);
  4. imagestring($captcha, 5, 16, 7, $_SESSION['tmptxt'], $colText);
  5. header("Content-type: image/gif");
  6. imagegif($captcha);

Crear el formulario para verificar el Captcha
Lo siguiente es mostrar la imagen generado para que el usuario pueda leerlo e ingresar el texto en el formulario para ser verificado. Naturalmente esta verificación será parte de un formulario mucho mas grande pero solo incluimos un campo para propósitos de ejemplo. Esto lo incluimos en el archivo captchademo.php, note que al incluir la imagen hemos colocado la ruta al php que genera la imagen.

HTML:
  1. Ingresar el texto mostrado en la imagen <br>
  2. <form action="captchademo.php" method="post">
  3.   <img src="captcha.php" width="100" height="30"><br>
  4.   <input name="tmptxt" type="text"><br>
  5.   <input name="btget" type="submit" value="Verificar Codigo">
  6.   <input name="action" type="hidden" value="checkdata">
  7. </form>

Verificar el texto Ingresado
Lo siguiente es verificar el texto ingresado en el formulario y compararlo con la variable $_SESSION['tmptxt'] que contiene el texto generado aleatoriamente. Para ello verificamos que se haya enviado el formulario y luego comparamos el texto ingresado con el texto que tenemos en la variable de sesión.

PHP:
  1. if ($_POST['action'] == "checkdata") {
  2.     if ($_SESSION['tmptxt'] == $_POST['tmptxt']) {
  3.         echo "Bienvenido";
  4.     } else {
  5.         echo "Inténtalo nuevamente";
  6.     }
  7.     exit;
  8. }

Ideas Adicionales
Nuestro ejemplo es sencillo, pero se puede mejorar esto por ejemplo dibujando lineas aleatorios con ángulos aleatorios sobre el texto, también se puede dibujar el texto con una inclinación aleatorio, también se pueden colocar cada letra con distintos ángulos de rotación y color. Con estos adicionales pueden lograr un Captcha mucho mas consistente y seguro.

Pueden ver el ejemplo funcionando en captchademo.php y también pueden descargar los archivos con las fuentes para que lo descarguen y prueben.

Posts Relacionados

Total de Comentarios: 46

Publicidad
22/08/2007
6:30 pm

Ahora acabaré de leer este buen post, me he quedado en el archivo captcha.php del cuál me ha encantado la sencillez de la función que defines para generar una cadena aleatoria. Llevo años utilizando otra bastante más complicada que me costó encontrar por ahí, que se basa en los códigos ASCII, y sinceramente, la tuya es de lejos mucho más elegante en cuanto a que es más sencilla pero muy potente.

Particularmente, para mi uso, le he hecho dos “mejoras”, que comparto aqui con vosotros: 1) usar la función mt_rand() en lugar de rand(), porque es más “fiable” y 4 veces más rápida (según doc oficial), 2) dar la posibilidad de llamar a la función pidiéndole cadenas aleatorias de 3 tipos (solo letras, solo numeros, letras y numeros).

function randomText($length,$type=0) {
switch ($type) {
case 0: $pattern = “1234567890abcdefghijklmnopqrstuvwxyz”; break;
case 1: $pattern = “abcdefghijklmnopqrstuvwxyz”; break;
case 2: $pattern = “1234567890″; break;
}
$max = strlen($pattern)-1;
for($i=0;$i

22/08/2007
6:32 pm

Perdón, la función se ha “truncado” por el signo “<”. La repito aquí:

function randomText($length,$type=0) {
switch ($type) {
case 0: $pattern = “1234567890abcdefghijklmnopqrstuvwxyz”; break;
case 1: $pattern = “abcdefghijklmnopqrstuvwxyz”; break;
case 2: $pattern = “1234567890″; break;
}
$max = strlen($pattern)-1;
for($i=0;$i < $length;$i++) $key .= $pattern{mt_rand(0,$max)};
return $key;
}

22/08/2007
7:13 pm

Muy bueno el post, y muy bien explicado. Me ha ayudado mucho ver lo fácil que es generar el gif :) y yo siempre pensando que era complicadisimo… jejeje

Si me lo permites, daré una alternativa a tu trabajo con sesiones (que nunca me ha gustado el tema este) para luego comprobar si la cadena introducida por el visitante coincide con la de la imagen.

El método que os propongo me parece mucho más sencillo y prácticamente infalible:

1.1- generamos una cadena aleatoria con mt_rand()
1.2- dibujamos un gif con esa cadena
1.3- encriptamos con md5() esa cadena
1.4- enviamos al visitante el formulario que contiene la imagen gif y un campo oculto con la cadena md5
2.1- el servidor recibirá la cadena escrita por el visitante y la cadena md5
2.2- encriptamos con md5() la cadena del visitante y vemos si coincide con la que iba oculta (correspondiente a la de la imagen)

Como veis, el proceso es practicamente el mismo que el de la comprobacion de logins en la mayoría de webs, en los que los paswords estan guardados en md5 en la BBDD.

No he utilizado hasta el momento este método, porque se me acaba de ocurrir, pero por de pronto me parece correcto. Pero se admiten réplicas ;)

22/08/2007
7:18 pm

Me faltó decir dos cosas:

1) para encriptar md5 en PHP:

$key_md5 = md5($key);

2) la función de encriptación md5, matemáticamente hablando es NO DESENCRIPTABLE, tan solo podría “reventarse por fuerza bruta” es decir probando trillones de combinaciones. Lo cuál en la práctica lo hace INDESCIFRABLE.

23/08/2007
6:46 am

Efectivamente como mencionas hay muchas formas para crear cadenas aleatorias y luego encriptarlas, en este caso use una forma sencilla para lograr la explicación centrada en la generación de la imagen, desde luego las ideas que has planteado servirán para que muchos visitantes mejoren sus aplicaciones.
Gracias.

24/08/2007
7:23 am

Hola; Tengo una duda… si realizas el formulario en FLash no hay para que realizar CaptCha o sí¿?

26/08/2007
3:03 am

Yo creo que si, pues al hacer el envío lo recibe un archivo PHP el cual acepta los datos por método POST por ejemplo, entonces para utilizar el captcha, se puede hacer un loadMovie de la imagen para mostrarla al usuario.

Blas
30/08/2007
9:39 pm

Hola a todos. Tengo un problema con el archivo “captcha.php”. No me muestra la imagen. Me dice que no se puede mostrar la imagen porque contiene errores. No es ningún error PHP ni nada por el estilo. Y tengo instaladas las librerías GD. El caso es q he probado a tocar un poco el código y tampoco. Si alguien me puede ayudar se lo agradecería.

Un saludo

Blas
30/08/2007
10:10 pm

Hola de nuevo, ya he solucionado el problema. El caso era que los gifs y los pngs no los admite la librería GD que tengo instalada. Lo he hecho con JPG y funciona perfectamente.

Gracias y un saludo.

P.D. Cojonuda la captcha eh?

03/09/2007
8:19 pm

[...] Crear CAPTCHA con PHP » unijimpe (tags: php) [...]

06/09/2007
4:47 am

no me sale la imajen y si pueden coloquen una descarga para eso de las librerias gd

18/09/2007
4:55 pm

Muy buen artículo!!

Me ha venido muy bien. Muchas gracias por compartirlo ;)

Elver Aroquipa Vilca
18/09/2007
6:50 pm

Hola Amigos, esto es un muy ejemplo y saludos a todo los que comparten sus script en php ..

10/10/2007
2:44 am

Hola.

Me descargue el fichero d captcha pero no me escribe el codigo en la imagen y tmp me aparece la imagen.

K tengo k acer?
Agradeceria k me contestaran al mail si puede ser o sino x aki.

Gracias!!!

samuel
21/10/2007
1:47 am

Hola amigos, muy bueno lo que comentan ahora tengo una duda, el paso 1 y 2 no es nada de otro mundo se re entiende, el tema va en el paso 3 y 4, resulta que yo eso lo quiero aplicar dentro un formulario ya generado…

por ejemplo estoy preparando un site para una rentacar y en ella inclui un formulario para la contratacion, y alli entonces dentro de ese formulario quiero incluir el capcha…Como tengo que hacer en este caso, con el paso 3 y 4, podrian ayudarme, tengo msn por si alguno me da una mano.
sherrera@iguanaserver.com

Gracias y muy buen aporte…

13/11/2007
4:08 pm

saludos quiero saver como crear un capsha para mi web no a sido posible

gracias

Marta Critins
14/01/2008
4:38 pm

hola no puedo hacerlo funcionar me da error

Cecik
08/02/2008
8:30 pm

Hola gracias por el script es de mucha ayuda, pero no se si estoy haciendo algo mal en pagina web por que no me aperece la imagen captcha.gif alguien me podria explicar? Gracias…

riverinyo
04/04/2008
2:56 am

Grande, grande!!!

Horas de curro que me acabo de saltar.
Muchas gracias por compartirlo!

Diego
08/04/2008
3:54 pm

Hola!
Che está muy bueno el código éste, funciona sin problemas.
Pensé que necesitaba la libreria gd o algo por el estilo, pero nada de eso.

Tuve unos problemas, pero los solucione.

Un Saludo grande.

15/04/2008
7:12 pm

Hola, estoy actualizando mi sitio web y estaba buscando algo práctico, sencillo pero útil como esto.

Muchas Gracias

no funciona
16/04/2008
12:47 am

cuando lo monte a un servidor directamente del archivo comprimido no funciona no SE VE LA IMAGEN ¿?..

05/05/2008
1:09 pm

Hola: genial tu artículo. Sólo una duda ¿por qué no lo has incorporado ha este formulario?.

Sergio
15/05/2008
3:04 am

Grácias por compartirlo con todos nosotros.

Sergio
15/05/2008
3:05 am

Un apunte, para que funcione correctamente en PHP5, he tenido que inicializar la variable $key=”".

23/05/2008
1:52 pm

unijimpe:
Excelente blog y el temas además.
Tengo un directorio (lo he escrito en website), le agregué el captcha y funciona, si no agregas el código te dice Inténtalo nuevamente y si lo hacer correctamente, te la la bienvenida. Mi problema es que no agrega el enlace, que debo de hacer, o de que forma debo de insertar el captcha?
Puedes verlo funcionando en:

http://www.entiempolibre.m-y-c.net/suggest_link.php?cat=Internet_&sub_cat=Blogs

Desde ya muchas gracias.

23/05/2008
8:32 pm

Hugo, lo que debes hacer es cambiar la linea donde se imprime el mensaje de bienvenido:

echo “Bienvenido”;

Y reemplazarlo por un header que redireccione a una pagina de confirmación del registro o agregar el codigo que guarde los datos enviados.

Hugo
24/05/2008
12:21 am

unijimpe:
Mi problema es que no se como hacerlo, No tienes idea de lo que me costo ubicar donde ponerlo, con php spy un caso, voy adivinando. con lo del header estoy nulo, si no es mucha molestia, te agradecería me indicaras como.

Muchas gracias de antemano.

Rodrigo
27/05/2008
1:38 pm

Hola

Muy Buen ejemplo, pero hay algo que no entiendo, en vez de usar

antes intente con y me arrojaba el tipico error de headers, como es entonces que los headers se envian antes al usar

thanxs

nightduke
30/05/2008
4:17 pm

Me puedes ayudar no consigo que me funcione el captcha.

Muchas gracias.

02/06/2008
7:21 am

Distingue MAYUSCULAS Y MINUSCULAS….

Jesus Neira
06/06/2008
10:43 am

Buenas, por favor me pueden guiar para solucionar el siguiente mensaje de error: Fatal error: Call to undefined function imagecreatefromgif(). Debo activar alguna librería, o tengo que configurar algo del conf?

09/06/2008
5:59 pm

holas me parece muy bueno el tema recien lo voy a probar pero dime se puede cambiar la fuente de las letras que salen en la imagen?

Jesus Neira
20/06/2008
4:40 pm

Buen día,

Ya encontre la solución, simplemente hay que instalar la librería GD en el servidor.

Gracias.

Matias
04/07/2008
9:19 am

Excelente la explicación. Lo implemente y logre evitar el ingreso de mensajes spam desde los formularios de contactos. Mi duda es respecto a un sistema de encuestas. Me pasa que varias veces alguna opcion se dispara porque evidentemente estan votando a traves de un robot (no se si intencionalmente o no…) ¿Es posible validar un voto en una encuesta a traves de un captcha? Si alguien sabe como, le agradeceria que me indique. Gracias, y saludos a todos.

Carlos-
31/07/2008
4:08 am

¡Eres mi idolo!

Te leo desde hace unas semanas y cada vez mas, hoy se dio el casual de que buscaba la manera de crear un captcha y captchuualidades de la vida encontré tu blog (por enesima vez cuando lo necesito).

Me encanta el estilo de la página y como lo explicas todo (para tonticos que estamos aprendiendo o que solo buscamos el código sin saber como funciona), creo que ya era hora de felicitarte por semejante web.

Un Saludo y me voy a probar este script!

Alejandro hdz.
05/08/2008
3:41 am

hola quue tal… soy nuevo en esto… he leido que es bueno eliminar las variables de sesion cuando ya no se usan por que son como una carga para el servidor… supongo que para cerrar la sesion o eliminar la variable de sesion lo hago justo despues de imprimir la bienvenida o me ekivoco??… y como algunos busco mandar un mail con un link de confirmación… pero siempre he tenido esta maldita duda…. asi como puedo mandar un mail de confirmacion a hotmail por ejemplo, como ellos no saben que mi intencion es mandar un spam?? no tendre ningun problema de mandar el link?? no esta restringido el envio de correo a hotmail desde un servidor localhost con dns gratutio registrado?? recuerdo que con mdaemon configure un servidor de correo y enviaba mails don un script php pero solo llegaba a yahoo a hotmail no llegaba… mmm.. de que depende esto??

Alejandro hdz.
05/08/2008
3:46 am

caos30… no se si tu codigo este bien…. veo que usas un switch para seleccionar una combinacion alfanuemerica, alfabetica o numerica… dependiendo el valor de $type… pero veo que siempre lo inicializas con cero… no sera que tu intencion es aplicarle un random a $type… $type=mt_rand(0,2); justo despues antes de que inicie el switch??

Alex
05/08/2008
2:53 pm

hice algo indebido?? ayer deje unos mensajes y ya no los veo… bueno ok. espero saber por que… ok. entiendo la funcion generadora pero entiendo poco el codigo que crea la variable de sesion… apartir de la linea del imagecreatefromgif… esta funcion por lo que lei crea una nueva imagen apartir de una archivo o un url…. pero como crea una imagen si lo que devuelve es un identificador??…. entonces es un identificador que representa o apunta a la imagen COPIA.. por que si crea una imagen apartir de otra entonces es una COPIA de la imagen..

Alex
05/08/2008
2:56 pm

otra cosa disculpen…. en el codigo zip veo que el formulario en su action tiene esto: action=”"…. que no se ni lo que signifique… y en este ejemplo de la pagina no sale asi solo dice action=”captchademo.php”… podrian explicarme… gracias… y disculpen si hice algo indebido en los post anteriores pero igual eran dudas y no podre resolverlas hasta que las encuentre por la web.. un saludo

Alex
05/08/2008
2:58 pm

una disculpa ya salieron los post… no se por que no habia aparecido en mi makina.. doy mucha lata… excelente blog..

Joseph
08/08/2008
1:43 pm

Hola….. excelente este tema… andaba buscando algo asi y tope con este… lo probe y me funciono de lo mas bien…

Ahora la pregutna que tengo es como puedo integrar/ agregar esto aun formulario de contactenos, he tratado pero no me da…

Cualquier ayuda se las agradecera….

nacho
27/08/2008
3:21 pm

hola estupendo scripth pero no me sale la imagen y no entiendo que hago mal ya que tengo un foro phpbb y si sale la imagen por lo que deduzco que tengo las librerias activados es que me servidor es gratis me ayudas.

Harold Lazo
05/09/2008
5:40 pm

Captcha mejorado con autorefresh por si el usuario no lo vé bien.

[CAPTCHA.PHP]
session_start();
function randomText($length, $type=0) {
switch ($type) {
case 0: $pattern = “1234567890abcdefghijklmnopqrstuvwxyz”; break;
case 1: $pattern = “abcdefghijklmnopqrstuvwxyz”; break;
case 2: $pattern = “1234567890″; break;
}
$max = strlen($pattern)-1;
for($i=0;$i < $length;$i++) $key .= $pattern{mt_rand(0,$max)};

return $key;
}

$_SESSION['tmptxt'] = randomText(5);

$captcha = imagecreatefromgif(”./images/bgcaptcha.gif”);
$colText = imagecolorallocate ($captcha, 0×00, 0×00, 0×00);
imagestring($captcha, 5, 20, 7, $_SESSION['tmptxt'], $colText);

header(”Content-type: image/gif”);
imagegif($captcha);

[FORMULARIO HTML]

Refrecar

[SCRIPT]
// funcion para actualizar captcha sin recargar la pagina

function actucap(){
var obj=document.getElementById(”cap”);
if (!obj) obj=window.document.all.cap;
if (obj){
obj.src= “captcha.php?” + Math.random() ;
}
}

Espero les sirva

Harold Lazo
05/09/2008
5:42 pm

el formulario ya que no salió

la imagen poner un <img id=”cap” …

y el link sería asi:

#refrescar

Harold Lazo
05/09/2008
5:43 pm

a href=javascript:actucap();

Enviar Comentario

(*)

(*)