Creando un captcha robusto con PHP

Bueno hoy vamos a ver la forma de crear un captcha propio que sea seguro.

Primero que nada veamos que es un captcha:
Se trata de una prueba desafio-respuesta utilizada para detrimar cuándo el usuario es o no humano. La prueba suele consistir en una imagen de la cual hemos de introducir unos carácteres o una simple pregunta.
En nuestro caso vamos a trabajar con captchas de imágenes.

Que necesitaremos para crear el captcha?

Aparte de lo evidente (PHP, servidor, etc..), necesitaremos tener habilitada la libreria GD (sabreis que no la teneis habilitada si al crear el code os dice que la función no existe) y si quereis podeis descargar el code de ejemplo para verlo más claro, tener las fuentes y la imagen que usaremos.

 Empezar con el captcha.

Antes de empezar vamos a abrir nuestro editor de imágenes y vamos a crear una pequeña imágen (yo elegí de 100×50).

En esta imagen pondremos un degrado de fondo del color que más nos guste y usaremos el dedo (smudge) para desenfocar y mezclar un poco los colores.

Tanto el degrado como el smudge servirán para dificultar el reconocimiento del captcha a los robots. Mi imagen final sería esta:
Fondo del captcha en color azul
Ahora vamos a crear el script. Primero que nada usamos session_start(); ya que usaremos una variable de sesión para comprobar el valor del captcha. Después de eso creamos una variable en la que almacenamos todos los carácteres a utilizar, en mi caso minúsculas, mayúsculas y números.

session_start();

//Len: 60
$cad = 'abcdefghijklmnopqrstvwxyzABCDEFGHIJKLMNOPQRSTVWXYZ0123456789';

Ahora tenemos que decidir la cantidad de carácteres que tendrá el captcha, yo he pensado en 4, así que creamos una variable de sesión y tomamos 4 valores aleatoriamente. Ya que son 60 carácteres, y un array empieza por el valor 0, tomaremos un número entre 0 y 59

//Captcha value:
$_SESSION['value'] = $cad[rand(0,59)].$cad[rand(0,59)].$cad[rand(0,59)].$cad[rand(0,59)];

A continuación empezaremos a utilizar la librería GD. Primero que nada crearemos la imagen a partir de nuestro fondo en png.

//Creando la imagen a partir del fondo
$img = imagecreatefrompng('captcha.png');

Ahora crearemos unos cuantos colores, el objetivo es asignar estos colores de forma aleatoria a los carácteres del captcha para dificultar la lectura a los bot.
Podemos crear tantos como queramos, como es un ejemplo solo he creado 4 colores. Cuando acabamos de crearlos los agregamos al array $colors.

//Creando colores:
$rojo = imagecolorallocate($img, 255, 0, 0);
$amarillo = imagecolorallocate($img, 255, 255, 0);
$violeta = imagecolorallocate($img, 0, 255, 255);
$azul = imagecolorallocate($img, 50, 150, 205);

$colors = array($rojo, $amarillo, $violeta, $azul);

En este punto ya estamos listos para agregar los carácteres a la imagen.
Lo normal usando la librería sería usar la función imagestring() pero en esta ocasión vamos a aprobechar la función imagettftext() para hacer aún más complicada la lectura del captcha por parte de un bot.
Los motivos son dos, el primero es que podemos usar la fuente que queramos y el segundo es que podemos marcar un ángulo de giro. Las tres fuentes del ejemplo se pueden descargar del paquete de ejemplo.

//Texto:
$fuentes = array('akbar.ttf', 'citizen.ttf', 'FGAaron.ttf');

imagettftext($img,  15, rand(0, 20), rand(10, 15), rand(30,35), $colors[rand(0, count($colors)-1)], $fuentes[rand(0, count($fuentes)-1)], $_SESSION['value'][0] );
imagettftext($img,  15, rand(0, 20), rand(30, 35), rand(30,35), $colors[rand(0, count($colors)-1)], $fuentes[rand(0, count($fuentes)-1)], $_SESSION['value'][1] );
imagettftext($img,  15, rand(0, 20), rand(50, 55), rand(30,35), $colors[rand(0, count($colors)-1)], $fuentes[rand(0, count($fuentes)-1)], $_SESSION['value'][2] );
imagettftext($img,  15, rand(0, 20), rand(70, 75), rand(30,35), $colors[rand(0, count($colors)-1)], $fuentes[rand(0, count($fuentes)-1)], $_SESSION['value'][3] );

La sintaxis de imagettftext es:

imagettftext('image resource', 'tamaño', 'ángulo de inclinación', 'x', 'y', 'color', 'fuente', 'texto');

Prestemos especial atención en:
– Ángulo de inclinación: Estamos usando la función rand() para dificultar la lectura a un robot
– Por el mismo motivo en los valores X e Y usamos rand()
– Así mismo hacemos uso de la misma función para elejir un color y una fuente aleatoria

De forma que tenemos 4 carácteres que cada vez toman 1 valor, una posición, una inclinación, un color y una fuente diferente. Para finalizar simplemente cambiamos los header y enviamos la imágen

//Mostrando la imagen
header("Content-type: image/png");
imagepng($img);
imagedestroy($img);

Como paso final dejo el código del index.php que se encarga de mostrar un formulario con el captcha y de validarlo.

<?php
session_start();

if ($_POST['send']) {
if ($_SESSION['value'] == $_POST['captcha'])
$text = 'Captcha correcto';
else
$text = 'Error al introducir el captcha';
}
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="https://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<meta name="author" content="Ignacio" />

<title>Sistema de Captcha</title>
</head>

<body>
<img src="captcha.php" />
<form action="<?php $_SERVER['PHP_SELF']; ?>" method="POST">
<input type="text" name="captcha" />
<input type="Submit" value="Enviar" name="send" />
</form>
<?php echo $text;?>


</body>
</html>

Si no quieren descargarse los archivos también pueden ver la demo online Espero les sea de utilidad

4 respuestas a «Creando un captcha robusto con PHP»

  1. No esta nada mal tampoco estaría mal un tuto para hacer que funciones con wordpress, smf, blogspot.. o no se como integrarlo..

    Y ahora unas preguntas referentes a la capcha…

    Que letras hay aquí ?

    https://img6.imageshack.us/img6/1434/sinnombrexk.jpg

    Supongo que la tercera no se entiende por el font que usar y el angulo de giro del que hablas mas arriba.

    Ahora bien unas preguntas técnicas.

    Supongamos que quiero poner varias imagen es de fondo, 3 o 4, diferentes estilos y colores que tengo que hacerle?

    Para que cada recarga me tire una imagen de fondo diferente.. se puede hacer eso ?

    Y lo mismo con el font, digamos que quiero usar varios tipos de font, no en cada letra pero si en cada capcha, osea que cada vez que vea la capcha haga una selección de varios aleatoria entre varios fonts…

    Complicado ? o solo agregar unas lineas de mas ? 😛

    Buen tuto, se entiende bien aunque el font no lo entiendo muy bien..

  2. el tema de los cms.. habría que adaptarlo según cada cms… lastima que no tengo muchos conceptos a nivel de programación de wp..

    el captcha pone:
    dyly
    aunque si.. cuesta un poco entender por la font y el angulo

    para el fondo simplemente tendrias que tener un array con los nombres de los fondos.. tipo:

    $fondos = array(‘fondo1.png’, ‘fondo2.png’,….);

    y al cargar la imagen haces:
    $img = imagecreatefrompng($fondos[rand(0, count($fondos)-1]);

    y así cargarias un fondo distinto cada vez… no se me habia ocurrido eso.. es buena idea.

    El tema de las fuentes… si quieres tener una fuente para todas las letras pero diferente en cada recarga hay que modificar una cosa…
    en la función: imagettftext() quitas esta parte:
    $fuentes[rand(0, count($fuentes)-1)]

    y pones alguna variable… y esa variable le pones la parte que quitaste…
    es decir:

    $fuente = $fuentes[rand(0, count($fuentes)-1)];

    imagettftext($img, 15, rand(0, 20), rand(10, 15), rand(30,35), $colors[rand(0, count($colors)-1)], $fuente, $_SESSION[‘value’][0] );

    y cambias todos los imagettftext así siempre usará la misma fuente.

    Por cierto volviendo al tema CMS…. se me ocurre que podrias tomar un complemento de WP con captchas.. y modificando ese crear tu propio captcha.. si me pasas alguno que cumpla tus expectativas y sea bastante simple al correo puedo mirarlo…

    saludos

  3. Hay uno bueno se llama capcha!

    Aunque es fácil de modificar creo ya que cuando lo instalas tienes que ponerle tus propias fuentes así que puedes escojer unas cuantas y el las usara..

    Pero bueno yo solo preguntaba a ver si era fácil

    Aquí en el foro tenemos dos capchas XD la de recapcha y otra que detecta spam no es un capcha pero detecta a los bots filtra los comentarios si a posteado un bot lo manda a papelera o a revisión depende de lo que escojas.. aunque creo que ahora esta deshabilitada …

    Gracias por la explicación tal vez diseñe unas imágenes y una capcha no creo que sea difícil adaptarla tomando en cuenta que puedes ver como estan hechas otras capchas libres..

    https://www.boriel.com/software/plugins/captcha-plugin/

    También viene por defecto en wordpress —> https://akismet.com/

    Detecta comentarios spam.. si los posteo un humano o un bot.. y manda a papelera.. es bastante bueno también…

Los comentarios están cerrados.

No usamos Cookies para rastrear nada, navega tranquilo...
Seguir Navegando
x