Captcha en CodeIgniter

Captcha significa Completely Automated Public Turing test to tell Computers and Humans Apart, que en otras palabras quiere decir que es una prueba automatizada que se utiliza para diferenciar si quien la realiza es una computadora o un ser humano. Para todos nosotros un Captcha es el código de letras y números que aparece en las webs cuando completamos un formulario y que muchas veces termina siendo molesto e incomprensible.

Lo cierto es que esta técnica sirve para brindar mayor seguridad a un sitio evitando el spam y los ataques por fuerza bruta.

El framework PHP CodeIgniter trae un asistente para utilizar Captchas y también documentación asociada. Sin embargo, creo que la información es un poco escueta y el código fuente adjunto no respeta el patrón MVC. Tal vez por cuestiones de simplicidad decidieron ilustrarlo de esa forma. De cualquier manera, voy a explicar cómo implementar el Captcha de CodeIgniter de forma clara y respetando el patrón mencionado.

Antes de comenzar, asegúrense de que su servidor tenga instalado la librería GD de PHP para manipulación de imágenes.

Permisos de archivo en el directorio Captcha

Cuando instalan CodeIgniter, verán que hay un directorio de nombre captcha. Allí se guardarán las imágenes que se generen mediante GD. El servidor debe tener permisos de escritura así que es necesario cambiar los permisos de este directorio. En un terminal pueden correr el siguiente comando.

Si están en un hosting y no tienen acceso vía SSH, tal vez el explorador de archivos que utilicen, o el FTP les permita cambiar los permisos a 777 (ó 666) como dice la documentación de CodeIgniter.

En el mismo directorio captcha encontrarán algunos archivos de fuentes con extensión ttf. Son los que utiliza la librería GD para generar las imágenes con el código.

Creación de la base de datos

El funcionamiento de este sistema de seguridad es básicamente de la siguiente manera. El usuario ingresa a la página que contiene un formulario. Esa página genera un código captcha utilizando GD y guarda el código generado en una tabla de la base de datos. Luego, el usuario ingresa el código que ve. El formulario se envía y al recibirlo se compara lo que ingresó el usuario con lo que hay guardado en la base de datos. Si existe, entonces el código ingresado es correcto y se acepta el formulario, si no, se rechaza y se vuelve a mostrar nuevamente el formulario generando un nuevo código captcha.

Entonces, es necesario la creación de una tabla en la base de datos. Esto obliga a trabajar con base de datos en CodeIgniter. Con el cliente de MySQL que prefieran pueden correr el siguiente código SQL.

El modelo

En la documentación de implementación el modelo y el controlador están juntos. Lo correcto es pasar las consultas a la base de datos a un archivo separado que se encuentre en el modelo de la aplicación. Sugiero crear un archivo captcha.php y ubicarlo en el directorio models con el siguiente contenido.

Si lo analizan de forma detenida, no agregué nada, simplemente adapté las sentencias SQL de la documentación oficial para que constituyan una única clase con los métodos necesarios. El constructor, insertCaptcha que sirve para insertar un nuevo captcha, deleteCaptcha que se encarga de eliminar el captcha una vez que expiró, y por último captchaExist que verificará su existencia y le servirá a la función de validación que se usará en el controlador.

El controlador

Aquí, vayamos por partes, primero veamos el constructor.

Primero, la llamada al método padre y la carga de los helpers o asistentes necesarios. Luego, he preferido cargar el modelo creado anteriormente en este constructor, antes que cargarlo en un método del controlador. El parámetro TRUE sirve para forzar la conexión a la base de datos en el momento de instanciación.

A continuación, viene el método del controlador que se encarga de enviar y recibir el formulario. Hay que utilizar la librería form_validation. Para simplificar la explicación sólo mostraré el campo de formulario vinculado al captcha, pero deben entender que en un formulario tradicional hay más campos y el código es más largo.

Se carga la librería form_validation. Luego se fijan las reglas de validación para el campo . Recuerden que irá una imagen con un elemento input debajo. Presten atención a la regla.

El primer valor required se refiere a la obligatoriedad de completar el campo. El segundo es el realmente interesante: callback_captcha_check. Se trata de un callback, es decir, una función de validación propia que definiremos más adelante.

Con set_message definimos el mensaje de error que se mostrará si el código ingresado es inválido. Cuidado con el primer parámetro: en esta ocasión no lleva la palabra “callback”.

El código que se ejecuta si se cumple el if es para cuando el formulario no pasa la validación o para cuando se muestra por primera vez.

Se carga el asistente de captcha de CodeIgniter

Y se crea el nuevo elemento captcha con el siguiente código

$vals es un array con las propiedades necesarias del Captcha. img_path debe tener la ruta donde está el directorio Captcha al que se le dieron permisos de escritura. img_url es la dirección URL absoluta a esa ubicación. font_path es la ruta a alguno de los archivos de fuentes que trae CodeIgniter que vimos al principio. Con img_width y img_height se puede definir las dimensiones de la imagen a generar. Luego, con expiration se establece en cuantos segundos expirará. 7200 equivale a 2 horas. Pueden definir las propiedades que mejor les parezca.

Finalmente, con create_captcha se creará el nuevo objeto Captcha cuya referencia quedará en $cap. La imagen se creará y se almacenará en el directorio captcha. Pueden chequearlo. No se preocupen porque pasado un tiempo, el mismo sistema se encarga de limpiar el directorio para que no se acumulen las imágenes de captchas expirados.

A continuación hay que insertar el captcha en la base de datos

Se crea un nuevo array con nuevos datos sobre el captcha que se insertarán en la base de datos. $cap[‘time’] y $cap[‘word’] no se definieron en el paso anterior, sin embargo su valor existe por defecto. El primero tiene la hora de creación del objeto y el segundo tiene el código que se le mostrará al usuario. El valor ‘ip_address’ sirve para guardar la ip del usuario que se conecta al sitio.

Luego, se hace la llamada al modelo creado y se inserta en la base de datos.

Validación con callback

Había comentado que se necesitaba una regla de validación especial. Esa regla está vinculada a una función de validación que se conoce como callback y que se trata nada más y nada menos de un método privado que se incluye en el mismo controlador.

Lo que hace este método es preguntar al modelo a través de captchaExist si el código captcha ingresado por el usuario es válido. Noten que los parámetros que se pasan son el código intruducido, la dirección IP del usuario y el tiempo de expiración. Por supuesto, este método devolverá TRUE o FALSE y de acuerdo a eso el mismo framework se encargará de que pase la validación o no.

La vista de formulario

Si repasan el controlador, verán que al final está la invocación a la vista, pasando previamente el objeto captcha a ella.

El objeto se pasa porque luego, en la vista, es necesario mostrar la imagen. Veamos como queda.

Al principio del archivo se definen los arrays con las propiedades de los elementos de formulario. En echo $cap[‘image’] se muestra la imagen del captcha.

Y en las siguientes dos líneas, el campo de texto para introducir el código con su correspondiente mensaje de error.

La vista no está formateada así que si toman este ejemplo puede que no se vea del todo bien. Igual, las partes más importantes son las que destaqué recién.

Conclusiones

El captcha es una herramienta imprescindible para mejorar la seguridad de los sitios web. El que trae  puede implementarse de forma sencilla. Primero hay que configurar correctamente el servidor asegurándose tener la librería GD instalada y los permisos correctos sobre el directorio captcha.

Luego, incluir el código que viene en la documentación de CodeIgniter pero desacoplando el modelo, el controlador y la vista para respetar el patrón MVC.

Soy programador web y me desempeño como Líder Técnico en Polar Bear Development. Trabajo con tecnologías como PHP, Javascript, MySQL y HTML5 para el desarrollo de sitios y sistemas web. Me especializo en Zend Framework 2 y otros frameworks MVC, como también en WordPress y otros CMS. Lidero equipos de desarrolladores trabajando con Scrum. Vivo en Buenos Aires, Argentina.
 

8 thoughts on “Captcha en CodeIgniter

  1. Muchas gracias por el tutorial. Como bien dices, la documentación de Codeigniter en algunas secciones es demasiado escueta e incluso confusa. Tutoriales como este nos hacen la vida más fácil. :)

  2. Gracias por tu comentario, Luis.
    Incluso en inglés hay poca información sobre este framework, un punto que le juega en contra en comparación de otros.

    Saludos

  3. Se hace una vez y se puede utilizar para siempre y sin depender de servicios de terceros. Si te parece demasiado, quizás sea conveniente que utilices algún framework, CMS o librería más genérica para tu proyecto. Algún tipo de solución ya armada, como por ejemplo un plugin.

    No olvides que aquí no solo estoy dando la solución, sino explicando la implementación, lo cual es una gran oportunidad para aprender a programar.

    Saludos

  4. Se te olvido usar el método (deleteCaptcha) para ir limpiando la DB.
    Por lo demás te felicito, me sirvió de mucho.
    Gracias.

Comments are closed.