Aprende a instalar y configurar correctamente BotDetect Captcha en tus formas nativas de Symfony 4.


Escribimos un artículo hace mucho tiempo, sobre cómo implementar Google ReCaptcha en su proyecto Symfony 3 , que funciona bien siempre que pueda confiar en la herramienta mencionada. Sin embargo, algunas aplicaciones restringen el uso de productos de Google. Por lo tanto, el desarrollador tendrá que implementar otra opción para evitar que los bots llenen formularios al azar en la web. Una de las bibliotecas más conocidas para lograr esto fácilmente en PHP es con la biblioteca de captcha BotDetect.

En este artículo, le explicaremos cómo instalar y usar la biblioteca BotDetect Captcha en Symfony 4.

1. Instale BotDetect Captcha

El generador BotDetect CAPTCHA es una solución de seguridad de formularios sin acecho que utiliza una combinación de medidas, que son fáciles para los humanos pero difíciles para los bots, para evitar la publicación automática de formularios. BotDetect también proporciona una alternativa de Captcha de audio para mantener los sitios web accesibles para las personas con problemas de visión, lo que le permite crear sitios web que cumplan con las WCAG y la Sección 508.

En Symfony 4, puedes instalar fácilmente la biblioteca a través del compositor usando el paquete symfony-captcha-bundle con el siguiente comando:

composer require captcha-com/symfony-captcha-bundle:"4.*"

Nota: Si estás utilizando Symfony 5, el paquete oficial aún no es compatible con esta versión. Sin embargo, @ carlos-mg89 decidió bifurcar el proyecto y crear un paquete compatible con Symfony 5 que puedes encontrar en el repositorio oficial de Github aquí , así que en lugar de seguir este tutorial, deberás seguir un paso adicional mencionado en la documentación del proyecto aquí.

Esto instalará la biblioteca y registrará sus clases automáticamente en su proyecto. Para obtener más información sobre esta biblioteca, visite el sitio web oficial aquí .

2. Registrar rutas de paquetes de Captcha

Para renderizar el captcha, solicitar audios, etc., deberá registrar las rutas que el paquete ya incluye en el archivo /config/routes.yaml de esta manera:

# /app/config/routes.yaml
captcha_routing:
    resource: "@CaptchaBundle/Resources/config/routing.yml"

Esto permitirá que el captcha funcione en el frontend una vez que se haya implementado en el backend.

3. Cree un archivo de configuración

Ahora necesitará crear un archivo de configuración en PHP en el directorio config / packages de su aplicación. Lo sé, generalmente agregamos solo archivos yaml en este directorio, sin embargo, esta biblioteca es un caso especial ya que tiene un requisito codificado que incluye un archivo PHP del directorio mencionado, por lo que deberá agregar obligatoriamente un archivo PHP con un simple if y un retorno con una matriz:

<?php 
// app/config/packages/captcha.php
if (!class_exists('CaptchaConfiguration')) { return; }

// Opciones de configuración de BotDetect PHP Captcha
return [
    // Configuración de captcha por ejemplo formulario
    'ExampleCaptchaUserRegistration' => [
        'UserInputID' => 'captchaCode',
        'ImageWidth' => 250,
        'ImageHeight' => 50,
    ],
];

La matriz asociativa devuelta tendrá como claves el nombre de la configuración personalizada de un solo campo. En este ejemplo, solo tendremos una única configuración de captcha que se utilizará para un formulario de registro de usuario. La idea es personalizar cada captcha donde lo necesite, puede especificar qué configuración se utilizará más adelante en FormType.

4. Agregue un campo CaptchaType a su FormType

Siguiendo las pautas de Symfony, cuando creamos un formulario, obviamente deberíamos tener un FormType asociado a alguna Entidad. En este caso, como mencionamos anteriormente, tendremos un formulario de registro que permite al usuario registrar un nuevo usuario en la base de datos, esto significa que el formulario persistirá como una entidad de Usuario en la base de datos. El formulario contiene los campos regulares como nombre, apellido, correo electrónico y contraseña. Sin embargo, también debe contener un nuevo campo, a saber, el código captcha, que se puede agregar simplemente al igual que los otros campos en el método buildForm del tipo.

Tenga en cuenta que el campo, aunque no está en la base de datos, debe agregarse como un campo mapeado, tal como se ve en el siguiente ejemplo:

<?php

// app/src/Form/RegistrationFormType.php
namespace App\Form;

// ... ///

// Importar el Validador y el Tipo de Campo Captcha
use Captcha\Bundle\CaptchaBundle\Form\Type\CaptchaType;
use Captcha\Bundle\CaptchaBundle\Validator\Constraints\ValidCaptcha;

// ... ///

class RegistrationFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            // ... ///

            ->add('captchaCode', CaptchaType::class, array(
                'captchaConfig' => 'ExampleCaptchaUserRegistration',
                'constraints' => [
                    new ValidCaptcha([
                        'message' => 'Captcha no válido, por favor intente de nuevo',
                    ]),
                ],
            ))

            // ... ///
        ;
    }

    // ... ///
}

Teóricamente, ahora se estaría preguntando a sí mismo que esto haría que su formulario fallara ya que estamos registrando un nuevo campo que no está asociado con la entidad Usuario, ¡y tiene razón! Pero no ejecutes tu aplicación todavía, sigue el último paso y entenderás por qué.

5. Agregue el campo captchaCode a su entidad

Finalmente, solo necesitará agregar un nuevo "campo" a su entidad, que no será mapeado por supuesto, solo es necesario que exista en la entidad que intentará persistir en la base de datos, para que la biblioteca pueda verificar si el captcha proporcionado por el usuario estaba bien o no:

<?php

// src/Entity/User.php
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

class User
{
    // ... //
    protected $captchaCode;
    
    public function getCaptchaCode()
    {
      return $this->captchaCode;
    }

    public function setCaptchaCode($captchaCode)
    {
      $this->captchaCode = $captchaCode;
    }

    // ... //
}

Con esto, ahora debería poder ejecutar su aplicación y verá el captcha. No olvide representar el nuevo campo en su vista de formulario:

{% extends 'base.html.twig' %}

{% block title %}Registrarse{% endblock %}

{% block body %}
    <h1>Register</h1>

    {{ form_start(registrationForm) }}
        {{ form_row(registrationForm.firstName) }}
        {{ form_row(registrationForm.lastName) }}
        {{ form_row(registrationForm.email) }}
        {{ form_row(registrationForm.plainPassword) }}
        {{ form_row(registrationForm.agreeTerms) }}

        {# renderizar el campo captcha al formulario en la vista #}
        {{ form_row(registrationForm.captchaCode) }}

        <button class="btn">Registrar</button>
    {{ form_end(registrationForm) }}
{% endblock %}

Cómo resolver el problema de incompatibilidad: Unexpected "spaceless" tag

Un par de usuarios informaron que en las últimas versiones de Symfony, donde se usa Twig 2.7, aparece la siguiente excepción:

Unexpected Spaceless Tag Twig

Esto sucede porque Twig decidió eliminar el soporte para el bloque sin espacio, convirtiéndolo en un filtro. El paquete de captcha no se ha mantenido durante mucho tiempo y, aunque un desarrollador @sumuhire decidió crear una solicitud de extracción para resolver el problema , aún no se ha fusionado. Para resolver este problema sin modificar nada en el directorio de proveedores de su proyecto, debe anular la plantilla de captcha predeterminada del paquete. Cree la siguiente estructura de directorios y el archivo captcha.html.twig dentro del directorio de plantillas de su proyecto (/your-app /templates/bundles):

templates
└── bundles/
   └── CaptchaBundle/
       └── captcha.html.twig

El contenido del archivo captcha.html.twig será el siguiente:

{# 
    sf4application/templates/bundles/CaptchaBundle/captcha.html.twig 
    https://github.com/captcha-com/symfony-captcha-bundle/pull/11/commits/a7d36269a192be90e71df28669238a3f7c50a550
#}
{% block simple_captcha_widget %}
    {% apply spaceless %}
        {{ captcha_html | raw }}
        {{ form_widget(form, { 'id': user_input_id, 'value': '' }) }}
    {% endapply  %}
{% endblock %}

{% block captcha_widget %}
    {% apply spaceless %}
        {{ captcha_html | raw }}
        {{ form_widget(form, { 'id': user_input_id, 'value': '' }) }}
    {% endapply  %}
{% endblock %}

Guarda los cambios y borre la caché de sus aplicaciones:

php bin/console cache:clear

Intenta acceder a tu aplicación una vez más y la excepción ya no aparecerá. Esto básicamente reemplazará la plantilla predeterminada de la biblioteca, evitando que aparezca esa tediosa excepción.

Cómo ocultar el mensaje "BotDetect CAPTCHA Library for Symfony"

Lamentablemente, la biblioteca no incluye una forma de ocultar ese mensaje ya que está codificado en la biblioteca, pero no debe modificar las clases de proveedores. Una solución para eliminar esto es a través de JavaScript, una vez que se haya cargado el DOM:

$(function(){
    $("a[title ~= 'BotDetect']").removeAttr("style");
    $("a[title ~= 'BotDetect']").removeAttr("href");
    $("a[title ~= 'BotDetect']").css('visibility', 'hidden');
});

Que te diviertas ❤️!


Interesado en la programación desde los 14 años, Carlos es un programador autodidacta, fundador y autor de la mayoría de los artículos de Our Code World.

Conviertete en un programador más sociable

Patrocinadores