Laboratorio: ejemplo de CAPTCHA
15:00 H (CET)| Temas: Laboratorio · PHP
El otro día ví en Rapidshare un ejemplo de CAPTCHA que parecía fácil de desarrollar. Se trata de las letras (tres en este caso), giradas ángulos aleatorios, pero no demasiado para que se pueda leer con facilidad, sobre un fondo de letras de tonalidad parecida, de menor tamaño y también giradas aleatoriamente.
Un ejemplo dinámico es el siguiente:
El método es muy sencillo, usamos una cadena de texto con todas las letras que queremos que aparezcan, para poder acceder aleatoriamente a cada una de ellas. Después nos crearemos el fondo de la imagen, siendo un gris claro y unas letras pequeñas, de un gris un poco más oscuro sobre ellas, que llenan toda la imagen. Y por último, creamos las tres letras del CAPTCHA para mostrarlas en el centro de la imagen y de un tamaño considerable.
En este caso he cogido la fuente de daFont, pero se puede usar la que se quiera. Yo recomiendo usar alguna que esté distorsionada para que la lectura para nosotros no presente complicaciones, pero si para algún proceso automático.
El script sería el siguiente, teniendo en cuenta que no se trata el almacenamiento en sesión de las letras del CAPTCHA para luego poder compararlas.
<?php
// Juego de letras para usar
$letras = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
// Configuración tamaño imagen y tamaño fuente
$ancho_caja = 200;
$alto_caja = 100;
$tam_letra = 16;
$tam_letra_grande = 60;
// angulo máximo que rota (izq y der) cada letra
$angmax = 20;
// Establecer el tipo de contenido
header("Content-type: image/png");
// Creamos una imagen
$im = imagecreate($ancho_caja, $alto_caja);
// Creo el color del texto, del texto del fondo y del fondo de la imagen
$gris = ImageColorAllocate($im, 200, 200, 200);
$colorLetra = ImageColorAllocate($im, 175, 175, 175);
$colorLetraFondo = ImageColorAllocate($im, 180, 180, 180);
// tipo de letra obtenido en dafont.net
$fuente = './Hotel Coral Essex.ttf';
// Calculo el número de líneas que entran
$caja_texto = imagettfbbox($tam_letra, 0, $fuente , $letras);
$alto_linea = abs($caja_texto[7]-$caja_texto[1]);
$num_lineas = intval($alto_caja / $alto_linea)+1;
// Dibujo las letras del fondo
// Cada letra de escribe de una en una para poder
// darle una rotación independiente al resto
$pos = 0;
for ($i = 0; $i<$num_lineas; $i++) {
$x = 0;
for ($j = 0; $j<30; $j++) {
$texto_linea = $letras[rand(0, strlen($letras)-1)].' ';
$caja_texto = imagettfbbox($tam_letra, 0, $fuente , $texto_linea);
imagettftext($im, $tam_letra, rand(-$angmax, $angmax), $x, $alto_linea*$i, $colorLetraFondo, $fuente , $texto_linea);
// Posicion x de la siguiente letra
$x += $caja_texto[2] - $caja_texto[0];
}
}
// Escribo las tres letras del CAPTCHA
$res = $letras[rand(0, strlen($letras)-1)];
$ang1 = rand(-$angmax, $angmax);
$caja_texto = imagettfbbox($tam_letra_grande, $ang1, $fuente , $res);
$y1 = abs($caja_texto[7]-$caja_texto[1]);
$x1 = abs($caja_texto[2]-$caja_texto[0]);
$res .= $letras[rand(0, strlen($letras)-1)];
$ang2 = rand(-$angmax, $angmax);
$caja_texto = imagettfbbox($tam_letra_grande, $ang2, $fuente , $res[1]);
$y2 = abs($caja_texto[7]-$caja_texto[1]);
$x2 = abs($caja_texto[2]-$caja_texto[0]);
$res .= $letras[rand(0, strlen($letras)-1)];
$ang3 = rand(-$angmax, $angmax);
$caja_texto = imagettfbbox($tam_letra_grande, $ang3, $fuente , $res[2]);
$y3 = abs($caja_texto[7]-$caja_texto[1]);
$x3 = abs($caja_texto[2]-$caja_texto[0]);
imagettftext($im, $tam_letra_grande, $ang1, ($ancho_caja/2)-(($x1+$x2+$x3)/2), $y1+($alto_caja-$y1)/2, $colorLetra, $fuente , $res[0]);
imagettftext($im, $tam_letra_grande, $ang2, ($ancho_caja/2)-(($x1+$x2+$x3)/2)+($x1), $y2+($alto_caja-$y2)/2, $colorLetra, $fuente , $res[1]);
imagettftext($im, $tam_letra_grande, $ang3, ($ancho_caja/2)-(($x1+$x2+$x3)/2)+($x1+$x2), $y3+($alto_caja-$y3)/2, $colorLetra, $fuente , $res[2]);
imagepng($im);
imagedestroy($im);
imagedestroy($im2);
?>
Un ejemplo lo podéis ver en la misma imagen que aparece arriba, ya que es dinámica y se modifica al recargar la página.
Relacionados
Feedback off | Del.icio.us
2. kevin ~ Viernes, 16 Feb 2007 | 23:53H:
Hola amigo, esta muy bueno tu script, pro perdona mi ignorancia, puedes explicarme como lo conecto con el formulario, es que soy nuevo en esto...
Gracias de antemano
4. carlos ~ Miércoles, 20 Jun 2007 | 00:38H:
hola me gustaria saber como seria el almacenamiento de las letras para luego compararlas a como se hacen en los captchas.
o si me podrias dar un enlace para averiguar soy nuevo en esto de php y captcha pero necesito saber.
gracias
6. carlos ~ Jueves, 21 Jun 2007 | 00:03H:
gracias por contestar pero en este ejemplo no muestra la manera de comparar las letras con las introducidas por caulquier persona es mas al principio el autor dice esto
Textual: El script sería el siguiente, teniendo en cuenta que no se trata el almacenamiento en sesión de las letras del CAPTCHA para luego poder compararlas.
y eso lo que necesito saber. como comparar lo que esta en la imagen con lo que una persona haya introducido
gracias de nuevo por tu repuesta
8. carlos ~ Jueves, 21 Jun 2007 | 16:46H:
muchicimas gracias Luis por la repuesta te lo agradezca voy a realizarlo a ver como me va.
gracias de nuevo y adios
9. carlos ~ Lunes, 25 Jun 2007 | 17:14H:
hola nuevamente, luis no he podido hacer la comprobacion,declaro la session como me recomendastes pero nada, siempre me responde que introduje bien las letras y es falso, hice la prueba de Ricard para ver las letras y no me muestra nada de nada, que me sugieres que haga.
SALUDOS
10. carlos ~ Lunes, 25 Jun 2007 | 19:41H:
si en el archivo captcha.php al principio declaro
<?php
session_start();
luego el codigo para generar el captcha
dentro coloco
$_SESSION['res']= $res;//para ke quede en session y pueda ser recuperado
luego en otro archivo llamado ver.php ago la comprobacion de lo que introduce la persona con las letras del captcha
<?php
session_start( );
if( $_POST[ 'texto_ingresado' ] != $_SESSION[ 'res' ] ) {
echo "Usted ingreso INCORRECTAMENTE el codigo.";
} else {
echo "El texto ingresado COINCIDE EXITOSAMENTE,GRACIAS!";
}
?>
y por ultimo en un archivo.html llamado formulario llamo a ambos archivos, esto es un trozo del archivo lo mas importante
<p align="center"><img src="captcha.php?<?php echo SID; ?>" /></p>
<form action="ver.php" method="POST">
<p>Ingrese el codigo:
<input name="texto_ingresado" type="text" id="texto_ingresado" size="30" />
<input type="submit" name="Submit" value="OK" />
SALUDOS Y GRACIAS POR TU TIEMPO,
11. carlos ~ Viernes, 29 Jun 2007 | 00:20H:
Luis, nada no consigo que me diga que es correcto lo que el usuario introduce QUE SERA?
vez algun problea en el codigo, yo uso Fedora 7, apache 2.2.4, php 5.2.2-3
SALUDOS
13. carlos ~ Lunes, 02 Jul 2007 | 18:14H:
Salu2 Luis
ya hice lo del var_dump asi, trozo del codigo
<?php
session_start( );
$a=$_SESSION[ 'texto' ];
var_dump ($a);
echo var_dump;
$b=$_POST[ 'texto_ingresado'];
var_dump ($b);
echo var_dump;
?>
esto es lo que me devuelve
la variable $a
NULL var_dump
la variable $b
string(3) "KRW" var_dump ---> esto es lo que la persona ve en la imagen del captcha, esta si me la captura bien parece que el problema esta en el SESSION del captcha no se como resolverlo. no soy experto en php, ESPERO UN CONSEJO PARA SOLUCIONARLO
¿como le hago?
GRACIAS POR TU TIEMPO
15. JinRoh ~ Martes, 03 Jul 2007 | 15:16H:
Para carlos ->
Usando tu código he conseguido hacer una versión funcional de tu mismo ejemplo.
El fallo está aqui:
if( $_POST[ 'texto_ingresado' ] != $_SESSION[ 'res' ] )
Te recuerdo que para comparar cadenas, debes usar el dobleigual (==) y no el simple (=)
Por lo que eso quedaria tal que asi:
if( $_POST[ 'texto_ingresado' ] == $_SESSION[ 'res' ] )
---------------
El codigo completo de ver.php sería:
---------------
El de form.php (o como se llame el formulario)
Ingrese el codigo:
-------------------------------
Y por último, solo debes añadir session_start(); al principio de captcha.php y $_SESSION["texto"] = $res; al final de ese mismo fichero.
Espero que te ayude.
16. JinRoh ~ Martes, 03 Jul 2007 | 16:02H:
Vuelvo a postear solo para comentar que ya he añadido el Captcha a mi pequeña página, concretamente al sistema de registro de usuarios, aunque realmente nunca he tenido ningun problema con "registros de spam", nunca viene mal una protección extra.
Eso sí, para conveniencia de los usuarios, he modificado los colores para hacerlos mucho más legibles (vamos, en lugar de gris para las letras he usado el naranja, que es el color de mi web).
¿El usar estos colores tan vivos merman la eficacia del captcha? Ver Ejemplo de mi captcha
17. carlos ~ Martes, 03 Jul 2007 | 23:00H:
Por fin ya esta hecho, muchas gracias a Luis por el Script y a JinRoh por tu aclaratoria tenias razon no era (!=) sino (==) ya todo funciona.
GRACIAS A AMBOS
18. JinRoh ~ Jueves, 05 Jul 2007 | 15:38H:
Hola, tengo una duda.
Para que el código se valide, debe escribirse en mayúsculas (tal y como aparece en la imagen)
¿Como podria hacer para que tambien se admitieran las minusculas?
¿O Como podria hacer para que un campo de texto, solo admita mayusculas (o que se cambien de minus a mayus automaticamente, vamos)? ¿es posible?

