Blogs Media: CSS Mania | VivirLatino | Sentido Web | Apps Mania

Publicidad

Mié03Ene2007

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:

CAPTCHA

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.

Código

Relacionados

Feedback (29) » Formulario

1. JL ~ Miércoles, 03 Ene 2007 | 19:04H:

Cuánto se aprende por aquí :)

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

3. Luis ~ Sábado, 17 Feb 2007 | 13:00H:

Hola Kevin, si eres nuevo en esto, casi mejor te recomiendo este enlace, porque quizás se te complique algo el hacerlo. Es mejor empezar poco a poco y luego ya ir metiendo cosas nuevas.

Saludos

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

5. Luis ~ Miércoles, 20 Jun 2007 | 08:10H:

El ejemplo es justo lo que tienes en este post.

Saludos

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

7. Luis ~ Jueves, 21 Jun 2007 | 09:45H:

Disculpa, hace mucho que hice el script y no me acordaba que no lo decía.

En $res tienes el texto, lo tendrás que meter en sesión, para que no viaje ($_SESSION["texto"] = $res) y luego, cuando el usuario meta el texto, tendrás que compararlo.

Saludos

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. Ricard ~ Sábado, 23 Jun 2007 | 21:23H:

hola, necesitaria algo mas de informacion, con la variable $res no me muestra las letras si hago un <? echo $res; ?>

que hago mal?

10. Luis ~ Domingo, 24 Jun 2007 | 13:08H:

Prueba con <?php echo $res; ?>

11. 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

12. Luis ~ Lunes, 25 Jun 2007 | 18:32H:

Has ejecutado session_start(); ??

13. 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,

14. 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

15. Luis ~ Viernes, 29 Jun 2007 | 12:31H:

Haz un var_dump de lo que tienes en sesión y de lo que te viene por el formulario para ver qué datos contienen.

16. 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

17. Luis ~ Martes, 03 Jul 2007 | 08:17H:

Pero es que en algún momento tienes que hacer $_SESSION['texto'] = $res, si no haces eso es como si nada, cuando lo recuperas no habrá nada nunca.

Saludos

18. 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.

19. 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

20. JinRoh ~ Martes, 03 Jul 2007 | 16:11H:

Una última nota :P . Finalmente decidi dejar los tonos grises, pero oscureciéndolos un poco para conseguir mayor legibilidad, de todas formas mantengo mi pregunta anterior, aunque ahora el ejemplo está alocado aquí , mientras que el que uso ahora es este

21. 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

22. 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?

23. Luis ~ Jueves, 05 Jul 2007 | 16:13H:

Deberías hacer lo siguiente:

if( strlower($_POST[ 'texto_ingresado' ]) == strlower($_SESSION[ 'res' ] ))

Así para que siempre compare los textos en minúsculas, introduzcas lo que introduzcas.

24. JinRoh ~ Viernes, 06 Jul 2007 | 15:01H:

Gracias por contestar, justo despues de escribir el mensaje, me puse a investigar un poco y no volvi aqui por lo que no vi tu mensaje, consegui esto:

if($_POST['captcha'] == $_SESSION['texto'] || $_POST['captcha'] == strtolower($_SESSION['texto']) )

Aunque tu codigo hace lo mismo y es más sencillo. Gracias

25. qualaydubpary ~ Miércoles, 09 Jul 2008 | 17:33H:

tests time mashine

26. qualaydubpary ~ Miércoles, 09 Jul 2008 | 22:35H:

tests time mashine

27. qualaydubpary ~ Viernes, 11 Jul 2008 | 09:36H:

tests time mashine

28. excinelapselp ~ Miércoles, 16 Jul 2008 | 17:06H:

this topic for test car

29. gjoppers ~ Miércoles, 30 Jul 2008 | 00:42H:

tests time mashine

Conversación

Nombre:

Email:

(no aparecerá)

URL:

(opcional)
¿Recordar datos?

↓ Comentarios (XHTML permitido)