recaptcha

Es común ver en formularios de una aplicación web un campo captcha, es decir, un campo donde el usuario debe introducir los caracteres presentes en una imagen distorsionada; esto con el fin de comprobar que quien esté usando la aplicación sea un humano. Podemos usar la solución que nos ofrece Google con reCAPTCHA, donde el usuario solo debe hacer clic en un checkbox y luego seleccionar un conjunto de imágenes según las condiciones que le solicita.  En este tutorial vamos a implementar reCAPTCHA para el login y registro de una aplicación de Laravel 5.2.

Configuración

Usaremos el paquete https://github.com/greggilbert/recaptcha el cual funciona para todas las versiones de Laravel 5 (5.0, 5.1 y 5.2) pero para este tutorial sólo vamos a implementarlo en un proyecto de Laravel 5.2 (para las demás versiones se siguen pasos similares). Para ello debemos tener un proyecto de Laravel 5.2 instalado con el registro y login que viene incluido en esta versión.

Instalamos el paquete vía Composer, agregando en require del archivo composer.json lo siguiente:

"greggilbert/recaptcha": "dev-master"

Luego incluimos el service provider del paquete en el array providers del archivo /config/app.php:

Greggilbert\Recaptcha\RecaptchaServiceProvider::class,

así como en el array alias del mismo archivo /config/app.php:

'Recaptcha' => Greggilbert\Recaptcha\Facades\Recaptcha::class,

Para publicar el archivo de configuración del paquete ejecuta:

php artisan vendor:publish --provider="Greggilbert\Recaptcha\RecaptchaServiceProvider"

Con esto ya lo tenemos disponible en /config/recaptcha.php

Para usar de manera correcta reCAPTCHA debes tener tu dominio registrado en https://www.google.com/recaptcha/admin para obtener las api key con las cuales vamos a trabajar:

api-keys-recaptcha

Éstas las vamos a agregar a nuestro archivo .env usando las claves del archivo config/recaptcha.php donde RECAPTCHA_PUBLIC_KEY será el Site key y RECAPTCHA_PRIVATE_KEY será Secret key

Para mi caso quedan así:

RECAPTCHA_PUBLIC_KEY=6LcG3B0TAAAAAMv7Nkgz2A1S_0gwFyc6Ys0ZD0RU
RECAPTCHA_PRIVATE_KEY=6LcG3B0TAAAAAPpRUfP2vIT-PPcXSTJXEA7Qxxh9

Uso

Como lo que queremos es agregar el reCAPTCHA a los formularios de registro y login de nuestra aplicación debemos agregar dos cosas: el campo y la regla de validación.

El paquete nos proporciona una vista con el campo reCAPTCHA ya listo para agregarlo dentro de un formulario, de esta manera:

{!! Recaptcha::render() !!}

Aunque si queremos personalizarlo podemos crear una nueva vista en /resources/views e indicar en la opción template del archivo /config/recaptcha.php el nombre de la nueva vista.

Para este ejemplo si vamos a personalizarlo con el fin de agregar estilos de Bootstrap y el mensaje de error, por tanto, crea el archivo /resources/views/recaptcha.blade.php con lo siguiente:

<?php
if (!function_exists('renderDataAttributes')) {
    function renderDataAttributes($attributes)
    {
        $mapped = [ ];
        foreach ($attributes as $key => $value) {
            $mapped[] = 'data-' . $key . '="' . $value . '"';
        };

        return implode(' ', $mapped);
    }
}
?>
<div class="form-group{{ $errors->has('g-recaptcha-response') ? ' has-error' : '' }}">
    <div class="col-md-6 col-md-offset-4">
        @if(!empty($options))
            <script type="text/javascript">
                var RecaptchaOptions = <?=json_encode($options) ?>;
            </script>
        @endif
        <script src='https://www.google.com/recaptcha/api.js?render=onload{{ (isset($lang) ? '&hl='.$lang : '') }}'></script>
        <div class="g-recaptcha" data-sitekey="{{ $public_key }}" <?=renderDataAttributes($dataParams)?>></div>
        <noscript>
            <div style="width: 302px; height: 352px;">
                <div style="width: 302px; height: 352px; position: relative;">
                    <div style="width: 302px; height: 352px; position: absolute;">
                        <iframe src="https://www.google.com/recaptcha/api/fallback?k={{ $public_key }}"
                                frameborder="0" scrolling="no"
                                style="width: 302px; height:352px; border-style: none;">
                        </iframe>
                    </div>
                    <div style="width: 250px; height: 80px; position: absolute; border-style: none;
                          bottom: 21px; left: 25px; margin: 0; padding: 0; right: 25px;">
                <textarea id="g-recaptcha-response" name="g-recaptcha-response"
                          class="g-recaptcha-response"
                          style="width: 250px; height: 80px; border: 1px solid #c1c1c1;
                                 margin: 0; padding: 0; resize: none;"></textarea>
                    </div>
                </div>
            </div>
        </noscript>
        @if ($errors->has('g-recaptcha-response'))
            <span class="help-block">
                <strong>{{ $errors->first('g-recaptcha-response') }}</strong>
            </span>
        @endif
    </div>
</div>

y modificamos el archivo /config/recaptcha.php para que use la vista que acabamos de crear:

'template' => 'recaptcha',

Para agregarlo al formulario de registro vamos al archivo /resources/views/auth/register.blade.php tan solo colocando {!! Recaptcha::render() !!}
dentro de la etiqueta <form>

Para agregar la regla de validación al registro vamos al archivo /app/Http/Controllers/Auth/AuthController.php y en el método validator colocamos la regla:

'g-recaptcha-response' => 'required|recaptcha',

Ya con esto tenemos al formulario de registro listo. Lo podemos ver ejecutando:

php artisan serve

y abriendo en el navegador http://localhost:8000/register vemos:
recaptcha-in-register-form

Si estás en tu entorno de desarrollo usando un virtual host puede ocurrir que te aparezca el error: ERROR for site owner: Invalid domain for site key.Esto es debido a que una key de reCAPTCHA está atada a uno o más dominios en particular, por tanto, debes añadir el virtual host a la lista de dominios permitidos en https://www.google.com/recaptcha/admin

Ahora para el formulario de login que se encuentra /resources/views/auth/login.blade.php
también tenemos que agregar el campo con {!! Recaptcha::render() !!}

y luego modificar las reglas de validación para el login, las cuales están en el método validateLogin del trait Illuminate/Foundation/Auth/AuthenticatesUsers.php, sin embargo, no podemos modificar directamente dicho método sino que lo sobreescribiremos en /app/Http/Controllers/Auth/AuthController.php quedando de esta manera:

protected function validateLogin(Request $request)
{
    $this->validate($request, [
        $this->loginUsername() => 'required', 'password' => 'required','g-recaptcha-response' => 'required|recaptcha',
    ]);
}

y visitando http://localhost:8000/login podremos visualizar el widget funcionando:
recaptcha-in-login-formPor último, nos queda configurar los detalles de los mensajes de error Laravel agregando en /resources/lang/en/validation.php en el array de validaciones:

'recaptcha' => 'The :attribute field is not correct.',

y para que el mensaje sea más claro para el usuario personalizamos el atributo

'attributes' => [
    'g-recaptcha-response' => 'Captcha'
],

Si nuestra aplicación es multi-idioma o está diseñada para otro idioma diferente del inglés agrega las líneas de arriba al archivo del idioma correspondiente /resources/lang/{lang}/validation.php.

Además puedes establecer el idioma por defecto de todos los reCAPTCHA de la aplicación colocando en el archivo /config/recaptcha.php por ejemplo, para idioma Español:

'options'     => [
    'lang' => 'es',
],

Espero te sea útil el tutorial. No olvides compartirlo en tus redes sociales.

Material relacionado

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.

Lección anterior Crea datos de prueba con Laravel test model factory helper Lección siguiente Manejo de traducciones en Laravel con themsaid/laravel-langman