• Josetxu.com
  • Perfil
  • Portafolio
  • Iconos
  • Demos
  • Blog
Blog · Josetxu.com

Captcha en PHP

Publicada en 7 dic 2017 de Josetxu

Captcha o CAPTCHA son las siglas en inglés de Completely Automated Public Turing test to tell Computers and Humans Apart, o lo que es lo mismo: Prueba de Turing completamente automática y pública para diferenciar ordenadores de humanos [+ info en wikipedia].
 

La validación de formularios para evitar a los bots es algo fundamental si no quieres recibir cantidades ingentes de correo basura. Hay múltiples opciones gratuitas como reCaptacha de Google, Securimage en PHP, o JCaptcha en Java, pero aqui lo vamos a hacer de manera artesanal con solo unas cuantas lineas de PHP y algunas de sus funciones.

Vamos a ello…

Captcha en PHP

En este artículo vamos a trabajar con dos archivos diferentes:

  • demo-captcha.php ========> que crea la imagen en png.
  • demo-captcha-form.php ==> que realiza la validación.

El Captcha

demo-captcha.php

Este archivo es el encargado de crear el captcha en formato image/png. Tambien crea la variable de sesión $_SESSION['captchaKey'] y le asigna el valor que hemos pintado en la imagen del Captcha para validarlo en el formulario, como veremos más adelante.

De momento vamos a crear el captcha en PHP.

Veamos el código por partes

Iniciamos sesión:

PHP
1
session_start();

Definimos el número de caracteres que tendrá el captcha:

PHP
1
$captchaTextSize = 5;

Con un bucle do y mientras se cumpla la condición dentro del while :

  • Creamos la variable $md5Hash con la funcion microtime() que devuelve el timestamp actual con microsegundos y la funcion mktime() que devuelve el timestamp de una fecha. Se multiplican ambos resultados y se codifican en md5 con la función md5(). El resultado es algo así: bdffe7ebff923061748cb436ab2501b0.
  • Creamos el array $xChar para excluir ciertos caracteres que pueden crear confusion:
    0 – O – o – 1 – l
  • Eliminamos los caracteres excluidos remplazándolos por nada.

PHP
1
2
3
4
5
do {
    $md5Hash = md5(microtime()*mktime());
    $xChar = array("0", "1", "o", "O", "l");
    $md5Hash = str_replace($xChar, "", $md5Hash);
} while(strlen($md5Hash)<$captchaTextSize);

A continuación creamos la variable $captchaKey con la cadena $md5Hash acortándola con la función substr() al tamaño definido en $captchaTextSize :

PHP
1
$captchaKey = substr($md5Hash, 0, $captchaTextSize);

Creamos una variable de sesión codificando $captchaKey en md5 y guardamos ahí el codigo que vamos a escribir en el captcha para disponer de él en el formulario:

PHP
1
$_SESSION['captchaKey'] = md5($captchaKey);

Seleccionamos una imagen (que debe existir previamente en su directorio) para crear el captcha, algo asi como la imagen de plantilla para el captcha final, usaremos la función imagecreatefrompng() pasándole una url de una imagen (recordar que debe existir previamente):

PHP
1
$captchaImage = imagecreatefrompng("../img/bg_captcha.png");

Definimos un color RGB para el texto de los caracteres con imagecolorallocate() :

PHP
1
$textColor = imagecolorallocate($captchaImage, 80, 80, 80);

También crearemos unas lineas aleatorias para dificultar la comprension del captcha sin que resulte excesivo para los humanos.
Definimos el color de las lineas aleatorias (yo le pongo el mismo color que el texto) :

PHP
1
$lineColor = imagecolorallocate($captchaImg, 80, 80, 80);

Definimos el ancho de las lineas aleatorias con la función imagesetthickness() :

PHP
1
imagesetthickness($captchaImage, 1);

Definimos el tamaño de la imagen con getimagesize() pasándole la url de una imagen existente:

PHP
1
$imageInfo = getimagesize("../img/bg_captcha.png");

Definimos el numero de lineas aleatorias con la funcion rand() de PHP:

PHP
1
$linesToDraw = rand(5,8);

Pintamos las lineas aleatorias con un bucle for. Para cada linea :

  • Definimos un punto inicial $xStart
  • Definimos un punto final $xEnd
  • Pintamos la linea en la imagen con la función imageline() que tiene 6 argumentos y son: imagen , posicion x inicial , posicion y inicial , posicion x final , posicion y final y color de linea .

PHP
1
2
3
4
5
for($i=0; $i<$linesToDraw; $i++){
  $xStart = mt_rand(0, $imageInfo[0]);
  $xEnd = mt_rand(0, $imageInfo[0]);
  imageline($captchaImage, $xStart, 0, $xEnd, $imageInfo[1], $lineColor);
}

Pintamos el código captcha en la imagen con la función imagettftext() de PHP. Los argumentos de esta función son 8: imagen , tamaño , ángulo , posicion x , posicion y , color del texto , url de la fuente de texto y el texto a escribir .

PHP
1
imagettftext($captchaImage, 20, 0, 10, 30, $textColor, "../../fonts/VeraBd.ttf", $captchaKey);

Declaramos los encabezados para exportar el archivo como imagen:

PHP
1
2
3
4
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");

Y finalmente imprimimos la imagen al archivo que leeremos desde el navegador con la función imagepng() :

PHP
1
imagepng($captchaImage);

Este es el código completo con comentarios:

demo-captcha.php

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?php /* CAPTCHA CON PHP */
  //iniciamos sesion
  session_start();
 
  //numero de caracteres para el captcha
  $captchaTextSize = 5;
 
  //haz esto...
  do {
    //creamos la variable $md5Hash que sera una cadena aleatoria
    $md5Hash = md5(microtime()*mktime());
    //array para excluir caracteres
    $xChar = array("0", "1", "o", "O", "l");
    //remplazar caracteres excluidos
    $md5Hash = str_replace($xChar, "", $md5Hash);
  } while(strlen($md5Hash)<$captchaTextSize); //...mientras se cumpla esto
 
  //creamos la variable $captchaKey del tamaño definido en $captchaTextSize
  $captchaKey = substr($md5Hash, 0, $captchaTextSize);
 
  //creamos variable de sesion codificando $captchaKey
  $_SESSION['captchaKey'] = md5($captchaKey);
 
  //seleccionamos imagen para el captcha
  $captchaImage = imagecreatefrompng("../img/bg_captcha.png");
 
  //color del texto
  $textColor = imagecolorallocate($captchaImage, 80, 80, 80);
 
  //color de lineas aleatorias
  $lineColor = imagecolorallocate($captchaImage, 80, 80, 80);
 
  //ancho de lineas aleatorias
  imagesetthickness($captchaImage, 1);
 
  //tamaño de imagen
  $imageInfo = getimagesize("../img/bg_captcha.png");
  //numero de lineas aleatorias
  $linesToDraw = rand(5,8);
 
  //para cada linea aleatoria...
  for($i=0; $i<$linesToDraw; $i++){
    //punto inicial
    $xStart = mt_rand(0, $imageInfo[0]);
    //punto final
    $xEnd = mt_rand(0, $imageInfo[0]);
    //pintamos la linea
    imageline($captchaImage, $xStart, 0, $xEnd, $imageInfo[1], $lineColor);
  }
  
  //pintamos el codigo en la imagen
  imagettftext($captchaImage, 20, 0, 10, 30, $textColor, "../../fonts/VeraBd.ttf", $captchaKey);
  //encabezados para enviar como imagen
  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");
 
  //imagen captcha final
  imagepng($captchaImage);
 
?>

Se ha añadido un botón para recargar el captcha y ver como cambia con cada actualización.

Además de la imagen (por detrás) tenemos guardada la variable de sesión $_SESSION['captchaKey'] que contiene el código que hemos escrito en la imagen.

Ya tenemos la imagen y el código de validación, ahora vamos a validar el Captcha en un formulario…

El Formulario

demo-captcha-form.php

El Captcha hay que validarlo en algún sitio, para ello crearemos otro archivo que será un formulario y que en este caso solo validará el captcha que hemos creado con el primer archivo.

Este archivo consta de dos partes, una primera parte de donde realizaremos la validación y una segunda parte que será formulario.

Vamos con la parte de la validación

Iniciamos sesión:

PHP
1
session_start();

Definimos una variable de sesión para mostrar el mensaje:

PHP
1
$_SESSION['mensaText']= "";

Con un if definimos lo siguiente:

  • Si no existe el campo captcha…
    • Definimos el mensaje de inicio
  • Si existe el campo captcha y además no es igual a la variable de sesion captchaKey (la que recibimos del primer archivo)…
    • Definimos el mensaje de error
  • Si las anteriores condiciones no se cumplen es porque que el captcha es correcto, entonces…
    • Definimos el mensaje de correcto
    • Borramos los campos guardados para vaciar el formulario

PHP
1
2
3
4
5
6
7
8
if ( !isset($_POST['captchaCode']) ) {
  $_SESSION['mensaText']='Escribe el codigo Captcha';  
} elseif( md5($_POST['captchaCode'])!=$_SESSION['captchaKey'] ) {
  $_SESSION['mensaText']='El Captcha no es correcto';
} else {
  $_SESSION['mensaText']='El CAPTCHA es correcto';
  unset($_POST);
}

Vamos ahora con la parte del formulario

En el formulario hay que tener en cuenta los atributos enctype="multipart/form-data" (necesario para enviar archivos) y method="POST" (para enviar los datos por HTTP) . Y dentro del formulario:

  • Pintamos el mensaje con la variable $_SESSION['mensaText'].
  • Pintamos un campo de texto para introducir el código del captcha.
  • Pintamos la imagen para el captcha y en el atributo src le ponemos la ruta del primer archivo que hemos creado, el que nos devolvía la imagen del captcha: demo-captcha.php.
  • Finalmente pintamos un boton para enviar el formulario.

Hay que recordar que junto a la imagen del captcha (por detras) recibimos una variable de sesión $_SESSION['captchaKey'] que tiene el valor del código del captcha, variable que ya hemos evaluado en la parte anterior de la validación, dentro del elseif .

PHP
1
2
3
4
5
6
<form enctype="multipart/form-data" method="POST" action="">
  <?php echo $_SESSION['mensaText']?><br>
  <input name="captchaCode" placeholder="captcha" type="text" value="" />
  <img src="./demo-captcha.php" alt="captcha" title="Código Captcha" />
  <input type="submit" name="enviar" value="COMPROBAR" />
</form>

Este es el código completo con comentarios:

demo-captcha-form.php

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
  //iniciamos sesion
  session_start();
  //declaramos una variable para el mensaje
  $_SESSION['mensaText']= "";
  //si no existe el codigo captcha...
  if ( !isset($_POST['captchaCode']) ) {
    //escribimos el mensaje de inicio
    $_SESSION['mensaText']='Escribe el codigo Captcha';
  //si existe, pero no coincide con la variable de sesion captchaKey
  } elseif( md5($_POST['captchaCode'])!=$_SESSION['captchaKey'] ) {
    //escribimos el mensaje de error
    $_SESSION['mensaText']='El Captcha no es correcto';
  //si no se cunple nada de lo anterior (si el captcha es correcto)
  } else {
    //escribimos el mensaje de correcto
    $_SESSION['mensaText']='El Captcha es correcto';
    //vaciamos los campos del formulario
    unset($_POST);
  }
?>
<form enctype="multipart/form-data" method="POST" action="">
  <?php echo $_SESSION['mensaText']; /* mensaje */ ?><br>
  <input name="captchaCode" placeholder="captcha" type="text" value="" />
  <img src="./demo-captcha.php" alt="captcha" title="Código Captcha" />
  <input type="submit" name="enviar" value="COMPROBAR" />
</form>

Escribe el codigo Captcha
Esto es solo el aspecto visual del formulario final, no funciona la validación.

Para ver la demo funcionando puedes hacer click en el siguiente botón:ver demo

Publicado en: PHP | Etiquetas: Captcha, Funciones, Imagen |
« Afinador de Guitarra – Online Guitar Tuner
» Aplicar estilos CSS a campos [radio] y [checkbox]

Artículos Relacionados

  • Imagen aleatoria con PHPImagen aleatoria con PHP
  • Funciones básicas en PHP: [include()] y [require()]Funciones básicas en PHP: [include()] y [require()]
  • Efecto Mouse ParallaxEfecto Mouse Parallax
  • Funciones básicas en PHP: [echo] y [print]Funciones básicas en PHP: [echo] y [print]
  • Efecto “Before / After” Responsive Efecto “Before / After” Responsive
josetxu Josetxu López

Diseñador y programador web multidisciplinar y autodidacta.
Investigo las posibilidades que nos ofrece la tecnología aprendiendo algo nuevo cada día. La curiosidad y la paciencia me han enseñado casi todo lo que sé...

Buscar

Categorías

  • CSS (7)
  • CSS3 (7)
  • HTML (4)
  • HTML5 (3)
  • Javascript (8)
  • JQuery (1)
  • PHP (6)

Etiquetas

Animación Audio Básico Captcha Clases Constructores Formularios Funciones Iconos Imagen JSON Métodos Responsive

Recientes

Crear pestañas de contenido o 'tabs' fácilmente con javascript
Crear pestañas de contenido o 'tabs' fácilmente con javascript
Funciones básicas en PHP: [include()] y [require()]
Funciones básicas en PHP: [include()] y [require()]
Iconos con CSS
Iconos con CSS
Aplicar estilos CSS a campos [radio] y [checkbox]
Aplicar estilos CSS a campos [radio] y [checkbox]

Utilidades

Color Picker w3c Selector de color Google Fonts google Fuentes de Google Can I use @Fyrd Soporte por navegadores Gimp gimp Manipulación de imágenes Notepad++ notepad++ Editor de código W3C Validator w3c Validador de código Highcharts highchartsGráficas en Javascript

Aviso

La información contenida en este blog es solo orientativa . No soy profesor, solo un tio curioso que quiere compartir lo aprendido durante estos años.

CyberChimps WordPress Themes

josetxu.comJosetxu.com Perfil | Portafolio | Iconos | Demos | Blog 2000 - 2020 © josetxu.com
▲