PHP: ¿Cómo hacer un código visual (imágenes) de seguridad? (CAPTCHA)

De Foros del Web

Muchos hemos querido desarrollar un código visual al estilo Google, Hotmail, etc... donde tenemos que escribir en un campo input el contenido de una imagen.

Este código fue originalmente solicitado por Section1, desarrollado por Cluster, con aportes de josemi, sin embargo... tenía algunos errorcitos pequeños de sintaxis que corregí.

Basicamente serían 4 archivos:

gen_codigo.php donde se generará el código que mostrará nuestra imagen

Código PHP:

<?php
function genera_password($longitud,$tipo="alfanumerico"){
 
if ($tipo=="alfanumerico"){
$exp_reg="[^A-Z0-9]";
} elseif ($tipo=="numerico"){
$exp_reg="[^0-9]";
}
 
return substr(eregi_replace($exp_reg, "", md5(time())) .
eregi_replace($exp_reg, "", md5(time())) .
eregi_replace($exp_reg, "", md5(time())),
0, $longitud);
}
?> 

tupagina.php

donde colocarás tu formulario y aparecerá la imagen generada

Código PHP:

<?php
// inicio uso sesiones.
session_start();
// aquí metes tu función genera_password
include ("gen_codigo.php");
// llamas a la función para generar un password.
$pass=genera_password(8);
// lo dejamos en una variable de sesión para poderlo leer de forma segura en otro proceso.php ...
$_SESSION['mipass']=$pass;
?>
<html>
</head>
</head>
<body>
<!-- .. etc y tu formulario con -->
<form action="procesa.php" method="POST">
 
<!-- la imagen generada con nuestro password ... -->
<img src="genera_img.php">
 
<input type="text" name="pass">
etc... campos y botón enviar ...
</form>
</body>
</html>


genera_img.php

el cual precisamente generará la imagen que contendrá el password generado por gen_codigo.php

Código PHP:

<?php
// Iniciamos uso de sesiones ...
session_start(); 
 
//recogemos el texto por el URL que enviamos a generar desde el link de imagen del HTML de nuestro formulario
$codigo=$_SESSION['mipass'];
 
//nombres tipografías a usar (sin extensión .ttf)
$tipografias = array("fuente1","fuente2");
 
//directorio donde estén las fuentes (ruta absoluta) importante el último /
$tipografias_ruta = "C:\WINDOWS\Fonts\\";
// $tipografias_ruta="/home/sito/public_html/fonts/"; linux
 
//inicializa eje X desde donde se empezará a dibujar el código (referente al tamaño de la caja)
$espacio = 0;
 
//tamaño fuente.
$tamano_fuente = 20;
 
//profundidad caracteres/digitos del código a generar (password).
$profundidad_codigo = 6; // (alfanuméricos)
 
//cálculo Ancho automático de la caja
$x=150;
$y=40;
$angmax = 20;
$hori = 50;
$verti = 100;
// Iniciar la generación de la imagen. Se define una caja de $x por $y pixels.
$im = imagecreate($x, $y);
 
 
//definición Colores. Expresados en valores R G B (respectivamente).
$color_fondo = imagecolorallocate($im, 255, 255, 255); // Blanco
$color_texto = imagecolorallocate($im, 0, 0, 0); // Negro
 
for($caracter=0; $caracter<$profundidad_codigo; $caracter++){
    $rhori = rand(-$hori, $hori);
    $rverti = rand(-$verti, $verti);
    // intento de lineas
    $lineColor = imagecolorallocate($im, 0, 0, 0);
    $lineColor2 = imagecolorallocate($im, 0, 0, 0);
    imagefill($im, 0, 0, $color_fondo);
    //imageline( imagen, separacion izq, separacion superior, largo, inclinacion)
 
    //linias horizontales
    imageline($im, 0, $rhori, 200, $rhori, $lineColor);
    imageline($im, 0, $rhori+20, 200, $rhori+20, $lineColor);
    // linias verticales, 
    imageline($im, $rverti, 0, 25, 700, $lineColor);
    imageline($im, $rverti+20, 0, 25, 700, $lineColor);
 
}
 
 
for($caracter=0; $caracter<$profundidad_codigo; $caracter++){
  //seleccion de una tipografía aleatoria.
  $indice_aleatorio=array_rand($tipografias);
  $tipografia=$tipografias_ruta.$tipografias[$indice_aleatorio].'.ttf';
 
  //separación entre caracteres
  $espacio +=$tamano_fuente;
  $ang = rand(-$angmax, $angmax); 
  //generar el caracter gráfico.
  //imagettftext($im, $tamano_fuente, 0, $espacio, $tamano_fuente, $color_texto, $tipografia , $codigo{$caracter});
  imagefttext($im, $tamano_fuente, $ang, $espacio, 30, $color_texto, $tipografia, $codigo{$caracter});
 
}
 
//cabecera HTTP la cual indica al navegador que la imagen que estamos generando es .PNG
header('Content-type: image/png');
 
//genera un png dinámico
imagepng($im);
//destruye la imagen del servidor
imagedestroy($im);
?> 

procesa.php

el cual mostrará el resultado en cuando al proceso, si la imagen es correcta o incorrecta.

Código PHP:

<?php
// inicio sesiones
session_start();
// Checamos que haya un valor en la sesion para evitar robots...
if(empty($_SESSION['mipass'])) {
    header("Location: tupagina.php");
}
// Checamos que haya un codigo minimo...
if(empty($_POST['pass'])) {
    echo "No escribiste nada";
}
// Comparamos los valores
if ($_SESSION['mipass'] == $_POST['pass']){
    echo "código/contraseña aceptado .. coincide ...";
} else {
    echo "Pues el código/contraseña NO coincide ...";
}
 
// Y nos deshacemos de la sesión ...
unset($_SESSION);
session_destroy();
?> 

Eso es todo. Asi crearemos el propio sistema seguro para que nuestros usuarios se registren en nuestra página sin usar robots. Muy util cuando nuestra web es muy recurrida. Suerte!

Discusión completa en: Como hacer un codigo visual de seguridad


--Takitei 27 Sep 2004

Este artículo es parte de las FAQs de PHP y el Manual de PHP.

Herramientas personales