DesarrolloLibre

Desarrollo Web, Android, juegos y mucho más

Categorias
04-12-2017

CodeIgniter cuenta con una gran cantidad de helpers y librerías tantos de terceros como propias que nos permiten emplear una gran cantidad de funcionalidades prácticamente sin hacer nada salvo crear las configuraciones necesarias para emplear dichas herramientas; una de estas herramientas que son bastante imprescindibles hoy en día son los captchas que son soportados de manera nativa (incorporado en el mismo framework) mediante la siguiente importación del helper:

$this->load->helper('captcha');

Dicha línea la podemos colocar en una clase, que heredará nuestro controlador, en cada acción o directamente en la acción de nuestro controlador; una vez realizado esto podemos crear el array de configuraciones para crear nuestro helper:

        $vals = array(
            'word' => 'Random word',
            'img_path' => './assets/captcha/',
            'img_url' => base_url() . 'assets/captcha',
            'font_path' =>  './system/fonts/font.ttf',
            'img_width' => '300',
            'img_height' => 80,
            'expiration' => 7200,
            'word_length' => 15,
            'font_size' => 48,
            'img_id' => 'Imageid',
            'pool' => '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
            // White background and border, black text and red grid
            'colors' => array(
                'background' => array(255, 255, 255),
                'border' => array(0, 255, 255),
                'text' => array(0, 0, 0),
                'grid' => array(255, 40, 40)
            )
        );

Finalmente, para crear y posteriormente mostrar nuestro capcha, empleamos la función create_captcha() de la siguiente manera:

 $cap = create_captcha($vals);

Lo que generará nuestro captcha y procedemos a pintarlo o establecerlo en una estructura para pasarlo a la vista, etc, en este caso solo lo mostramos por pantalla:

echo $cap['image'];

Finalmente todo el código:

    public function captcha() {

        $this->load->helper('captcha');

        $vals = array(
            'word' => 'Random word',
            'img_path' => './assets/captcha/',
            'img_url' => base_url() . 'assets/captcha',
            'font_path' =>  './system/fonts/font.ttf',
            'img_width' => '300',
            'img_height' => 80,
            'expiration' => 7200,
            'word_length' => 15,
            'font_size' => 48,
            'img_id' => 'Imageid',
            'pool' => '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
            // White background and border, black text and red grid
            'colors' => array(
                'background' => array(255, 255, 255),
                'border' => array(0, 255, 255),
                'text' => array(0, 0, 0),
                'grid' => array(255, 40, 40)
            )
        );

        $cap = create_captcha($vals);
        echo $cap['image'];
    }

Que mostraría una imagen en nuestro navegador como la siguiente:

Que mostraría una imagen como la promocional al inicio de esta entrada.

En caso de que no especifiquemos la palabra que compone al captcha, para obtener las palabras en texto plano para poder validarlos con la respuesta del usuario empleamos la siguiente asignación:

echo $cap['word'];

La función create_captcha() devuelve un array con los siguientes elementos:

array(
        'image' => IMAGE TAG
        'time'  => TIMESTAMP (in microtime)
        'word'  => CAPTCHA WORD
)

Configurando el helper del captcha con la base de datos

El propósito de los captchas no solo es generar la ya conocida imagen con los textos distorsionados, sino también de validar la respuesta de un usuario con las palabras escritas en el captcha y de esta forma "garantizar" que el internauta sea un usuario y no un robot, para eso lógicamente tenemos que comparar el texto empleado para generar el captcha con la respuesta del usuario, podríamos inventarnos varias formas de tener guardado el texto empleado para generar el captcha para posteriormente compararlo con el texto suministrado por el usuario, una forma sería guárdalo en una variable en sesión; algo como lo siguiente:

        $this->session->set_userdata(array(
            'captcha_texto' => $cap['word']
        ));

Y posteriormente consultamos dicha variable en sesión con la respuesta del usuario cuando este envie la petición del formulario; la otra forma algo más profesional y limpia es emplear el esquema que proponen en la documentación oficial, que es guardar dicho texto en un registro junto con el nombre de la imagen; para ello empleamos una tabla como la siguiente:

CREATE TABLE captcha (
        captcha_id bigint(13) unsigned NOT NULL auto_increment,
        captcha_time int(10) unsigned NOT NULL,
        ip_address varchar(45) NOT NULL,
        word varchar(20) NOT NULL,
        PRIMARY KEY `captcha_id` (`captcha_id`),
        KEY `word` (`word`)
);

En general, el esquema que plantean es bastante simple y muy funcional, como podemos ver en el método que genera y pinta el capcha registran la IP del usuario que consulta la web junto con el nombre de la imagen del captcha y la frase empleada para generar el mismo:

    public function captcha1() {

        $this->load->helper('captcha');

        $vals = array(
//            'word' => 'Random word',
            'img_path' => './assets/captcha/',
            'img_url' => base_url() . 'assets/captcha',
            'font_path' => './system/fonts/font.ttf',
            'img_width' => '300',
            'img_height' => 80,
            'expiration' => 7200,
            'word_length' => 15,
            'font_size' => 48,
            'img_id' => 'Imageid',
            'pool' => '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
            // White background and border, black text and red grid
            'colors' => array(
                'background' => array(255, 255, 255),
                'border' => array(0, 255, 255),
                'text' => array(0, 0, 0),
                'grid' => array(255, 40, 40)
            )
        );

        $cap = create_captcha($vals);

        $data = array(
            'captcha_time' => $cap['time'],
            'ip_address' => $this->input->ip_address(),
            'word' => $cap['word']
        );

        $query = $this->db->insert_string('captcha', $data);
        $this->db->query($query);

        echo 'Submit the word you see below:';
        echo $cap['image'];
        echo '/<input type="text" name="captcha" value="" />';
    }

En el siguiente método se encarga de recibir y validar los datos del usuario y de la respuesta introducida por el usuario al descifrar las letras que están en el capcha, además aquí se encarga de hacer una limpieza cuya duración exceda del tiempo de vida de la imagen de los captchas que para este ejemplo es de dos horas en la base de datos y de buscar coincidencias entre la frase introducida por el usuario (IP), con la del captcha, como podemos ver, no necesariamente buscará por un registro del captcha para ese usuario (IP) si no SOLO las que tengan una duración de a lo sumo dos horas (7200 segundos), por lo tanto si el usuario solicita múltiples veces el capcha (digamos tres) antes del tiempo estipulado para realizar la limpieza en la base de datos (para este ejemplo es de dos horas -7200 segundos-) dicha comprobación en base de datos se realizará con todos los registros de captchas que solicitara el usuario y generará la aplicación.

    public function captcha2() {

// First, delete old captchas
        $expiration = time() - 7200; // Two hour limit
        $this->db->where('captcha_time < ', $expiration)
                ->delete('captcha');

// Then see if a captcha exists:
        $sql = 'SELECT COUNT(*) AS count FROM captcha WHERE word = ? AND ip_address = ? AND captcha_time > ?';
        $binds = array($_POST['captcha'], $this->input->ip_address(), $expiration);
        $query = $this->db->query($sql, $binds);
        $row = $query->row();

        if ($row->count == 0) {
            echo 'You must submit the word that appears in the image.';
        }
    }

Si deseas que SOLO compare con un registro y que este sea del captcha actual, simplemente hay que eliminar todos los capchast solicitados por el usuario (IP) al momento de generar el captcha:

    public function captcha1() {

        $this->load->helper('captcha');

        $vals = array(
//            'word' => 'Random word',
            'img_path' => './assets/captcha/',
            'img_url' => base_url() . 'assets/captcha',
            'font_path' => './system/fonts/font.ttf',
            'img_width' => '300',
            'img_height' => 80,
            'expiration' => 7200,
            'word_length' => 15,
            'font_size' => 48,
            'img_id' => 'Imageid',
            'pool' => '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
            // White background and border, black text and red grid
            'colors' => array(
                'background' => array(255, 255, 255),
                'border' => array(0, 255, 255),
                'text' => array(0, 0, 0),
                'grid' => array(255, 40, 40)
            )
        );

        $cap = create_captcha($vals);

        $data = array(
            'captcha_time' => $cap['time'],
            'ip_address' => $this->input->ip_address(),
            'word' => $cap['word']
        );

        $this->db->where('ip_address = ', $this->input->ip_address())
                ->delete('captcha');

        $query = $this->db->insert_string('captcha', $data);
        $this->db->query($query);

        echo 'Submit the word you see below:';
        echo $cap['image'];
        echo '/>input type="text" name="captcha" value="" />';
    }

Obviamente debemos colocar las consultas en los modelos, crear las vistas, pero la idea del código anterior es mostrar la idea en general sin que se complique con otros detalles de menor importancia; puedes consultar la documentación oficial en el siguiente enlace: CAPTCHA Helper CodeIgniter.

La tabla de los captchas es la siguiente:

CREATE TABLE captcha (
        captcha_id bigint(13) unsigned NOT NULL auto_increment,
        captcha_time int(10) unsigned NOT NULL,
        ip_address varchar(45) NOT NULL,
        word varchar(20) NOT NULL,
        PRIMARY KEY `captcha_id` (`captcha_id`),
        KEY `word` (`word`)
);

Publicidad

Give me for a beer!

Algunos recursos que te pueden interesar

Efectos hover con CSS

Efectos hover con CSS

API REST en CodeIgniter

API REST en CodeIgniter

CompressNow: optimiza tus imágnes GIF, JPG y PNG.

CompressNow: optimiza tus imágnes GIF, JPG y PNG.

Algunos artículos que te pueden interesar

Login Social en Twitter con PHP-CodeIgniter y la Twitteroauth

Login Social en Twitter con PHP-CodeIgniter y la Twitteroauth

Andrés Cruz 23-02-2017

Url_title() en CodeIgniter

Url_title() en CodeIgniter

url_title permite crear URLs amigables que nos favorece al momento del SEO.

Andrés Cruz 25-06-2013

¿Cómo obtener imágenes en Escala de Grises con solo HTML5?

¿Cómo obtener imágenes en Escala de Grises con solo HTML5?

En esta nueva entrega veremos cómo obtener imágenes en Escala de Grises o en Blanco y Negro con HTML5.

Andrés Cruz 10-07-2014