Instalación de reCaptcha de Google en tu proyecto Angular/Angular Universal (o en otros proyectos cómo Vue, React, etc).

¿Alguna vez has entrado en un sitio web y al rellenar algún formulario fue necesario "demostrar" que eres un ser humano a través de un prueba?

Esa validación con texto ligeramente distorsionado o selección de imágenes se conoce como reCAPTCHA, un recurso de seguridad de Google diseñado para proteger sitios web contra spam y actividades abusivas, distinguiendo a los humanos de los bots automatizados.

En este articulo vamos a enseñar a instalar el siguiente reCAPTCHA, paso a paso, en vuestro proyecto angular universal.

Os dejo el repositorio https://github.com/al118345/angular_recaptcha_gooogle para su consulta y el siguiente video explicativo:

Alta en google.

En este artículo partimos con la premisa de que posees una cuenta de Gmail.

El primer paso es darse de alta en la url https://www.google.com/recaptcha/admin/create. Una vez accedemos y estemos logueados en la cuenta de Gmail aparecerá el siguiente formulario a rellenar.

Importante: Realizar dos inscripciones, una para el dominio escogido y otra con localhost con el objetivo de realizar las pruebas previas a la puesta en producción.

Rellenado el formulario aparecerá la siguiente pantalla con la información acerca de la clave para utilizar el servicio.

Instalación con HttpClientModule de Angular.

Primero de todo, a través del link al siguiente repositorio https ://github.com/al118345/angular_recaptcha_gooogle/tree/main/src/app/components/asincrono puedes acceder a un ejemplo de este tipo de comunicación. Con respecto al backend tienes el siguiente ejemplo en el repositorio https://github.com/al118345/TestComunicacionApiRest_Angular

Para realizar esta instalación, hay que dividir el proyecto entre un front-end y un back-end. Dentro del front-end, en esta parte del proyecto hemos escogido utilizar una librería de Angular que permite realizar comunicaciones con el back-end. La librería se llama HttpClientModule.

Si tu proyecto va a utilizar otra framework, por ejemplo, React, Vue, etc, deberás buscar la librería que mejor se adapte a tu proyecto. Una librería multiplataforma es XmlHttpRequest https://www.npmjs.com/package/xmlhttprequest y os dejo un ejemplo de cómo utilizarla en el siguiente punto de este proyecto.

Dicho esto, con HttpClientModule realizaremos una comunicación asíncrona. El front realizará la interacción con el usuario y el backend se comunicará con Google pero el usuario no percibe dicho trabajo. La navegación no se detiene y puedes, por ejemplo, mostrar un código de esperando la respuesta en la web.

Desde Angular realizaremos la instalación del paquete ng-recaptcha con el siguiente comando:
npm i ng-recaptcha --force

Además crearemos el siguiente servicio para comunicarse con la api de Python.

ng generate service service/recaptcha
import {Inject, Injectable, PLATFORM_ID} from '@angular/core';
import {isPlatformBrowser} from '@angular/common';
import { Observable, throwError} from 'rxjs';
import {HttpClient, HttpHeaders} from '@angular/common/http';
import {catchError, map} from "rxjs/operators";

@Injectable({
  providedIn: 'root'
})
export class RecaptchaService {
  constructor(private http: HttpClient) {
  }
  /*
  Modo de comunicación con el servidor asíncrono
  parametro token: string
  return Observable<any>
   */
  getTokenClientModule(token: string): Observable<any> {
    const httpOptions = {
      headers: new HttpHeaders({
        'Content-Type':  'application/json',
      })
    };
      return this.http.post<any>( 'http://0.0.0.0:5000/api/v1/verificar/' + token +'/', httpOptions)
        .pipe(
          map((response) => response),
          catchError((err) => {
            console.log('error caught in service')
            console.error(err);
            return throwError(err);
          })
        );
  }
}

Importamos el módulo a nuestra app con el siguiente código:

import {RECAPTCHA_V3_SITE_KEY, RecaptchaV3Module} from 'ng-recaptcha';


@NgModule({
  declarations: [],
  imports: [
   RecaptchaV3Module,
   HttpClientModule


  ],
  providers: [
    {
    provide: RECAPTCHA_V3_SITE_KEY,
    useValue: 'pon_la_key_de_google',
  }]
})
Y añadiremos la funcionalidad en el componente:
<div class="container">
    <div class="row">
        <div *ngIf="robot == true">
          <p >Ejemplo de ejecución HttpClient(asincrona) de google recaptcha
          </p><button (click)="getInfoRecaptcha()" class="btn btn-primary">
          Comprobación</button>
        </div>
    </div>
</div>
<div *ngIf="presionado == true">
  <p>Cargando ...</p>
</div>

<div *ngIf="robot == true">
    <p>De momento eres un robot, presiona el botón</p>
</div>
<div *ngIf="robot == false">
    <p>No eres un robot, Enhorabuena </p>
</div>

 public robot: boolean;
  public presionado: boolean;

  constructor( private httpService: RecaptchaService,  private recaptchaV3Service: ReCaptchaV3Service) {
    this.robot = true;
    this.presionado = false;
  }

  ngOnInit(): void {
    this.robot = true;
    this.presionado = false;
  }

  getInfoRecaptcha() {
    this.robot = true;
    this.presionado = true;
    this.recaptchaV3Service.execute('')
      .subscribe((token) => {
          const auxiliar = this.httpService.getTokenClientModule(token)
          auxiliar.subscribe( {
            complete: () => {
              this.presionado = false;
            },
            error: () => {
              this.presionado = false;
              this.robot = true;
              alert('Tenemos un problema, recarga la página página para solucionarlo o contacta con 1938web@gmail.com');
            },
            next: (resultado: Boolean) => {
              if (resultado === true) {
                this.presionado = false;
                this.robot = false;
              } else {
                alert('Error en el captcha. Eres un robot')
                this.presionado = false;
                this.robot = true;
              }
            }
          });
        }
      );
  }

Por último, modificamos la api para recibir la petición del front-end creando la siguiente ruta en el proyecto https://github.com/al118345/envio_email_api_python
class Verificar_Captcha(Resource):
        def post(self, token):
            recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify'
            recaptcha_secret_key = ''
            payload = {
                'secret': recaptcha_secret_key,
                'response': token,
                'remoteip': request.remote_addr,
            }
            response = requests.post(recaptcha_url, data=payload)
            result = response.json()
            return result.get('success', False)

local_resources = [
    (Verificar_Captcha, '/verificar/<string:token>/'),
]
Para terminar, en la web https://www.google.com/u/3/recaptcha/admin/ puedes consultar una vista como la siguiente imagen dónde puedes comprobar la cantidad de gente que ha realizado el login y la puntuación obtenida de media.

Ejemplo en ejecución presionando un botón

Ejemplo de ejecución HttpClient(asíncrona) de google recaptcha

¿Eres un robot?. Según recaptcha de Google de momento eres un:

Eres un robot

Instalación con de forma síncrona con XmlHttpRequest

Importante, con esta instalación la ejecución de vuestra web se detendrá hasta obtener el resultado del captcha. Es decir, no puede mostrar un cartel de cargando o realizando ningún tipo de scroll.

Primero de todo, a través del link al siguiente repositorio https ://github.com/al118345/angular_recaptcha_gooogle/tree/main/src/app/components/sincrono puedes acceder a un ejemplo de este tipo de comunicación. Con respecto al backend tienes el siguiente ejemplo en el repositorio https://github.com/al118345/TestComunicacionApiRest_Angular

Para realizar esta instalación, hay que dividir el proyecto entre un front-end y un back-end. El front realizará la interacción con el usuario y el backend se comunicará con Google.

Desde Angular realizaremos la instalación del paquete ng-recaptcha con el siguiente comando:
npm i ng-recaptcha --force

Además crearemos el siguiente servicio para comunicarse con la api de Python.

ng generate service service/recaptcha
import {Inject, Injectable, PLATFORM_ID} from '@angular/core';
import {isPlatformBrowser} from '@angular/common';
@Injectable({
  providedIn: 'root'
})
export class RecaptchaService {

  constructor() {
  }

 /*
  Modo de comunicación con el servidor síncrono
  parametro token: string
  return string
   */
  getToken(token: string): string {
      const xhr = new XMLHttpRequest();
      xhr.open('POST', 'urldestino' + token, false);
      xhr.send();
      return  xhr.responseText ;
  }
}

Importamos el módulo a nuestra app con el siguiente código:

import {RECAPTCHA_V3_SITE_KEY, RecaptchaV3Module} from 'ng-recaptcha';
@NgModule({
  declarations: [],
  imports: [
   RecaptchaV3Module

  ],
  providers: [
    {
    provide: RECAPTCHA_V3_SITE_KEY,
    useValue: 'pon_la_key_de_google',
  }]
})
Y añadiremos la funcionalidad en el componente:

<h1>Ejecución XmlHttpRequest</h1>
<div class="container">
    <div *ngIf="robot == true">
          <p class="fw-light lead mb-4">Ejemplo de ejecución XmlHttpRequest (sincrona) de google recaptcha
          </p><button (click)="getInfoRecaptcha()" class="btn btn-primary">
          Comprobación</button>
    </div>
</div>
<div *ngIf="robot == true">
    <p>De momento eres un robot, presiona el botón</p>
</div>
<div *ngIf="robot == false">
    <p>No eres un robot, Enhorabuena </p>
</div>

  public robot: boolean;
  public presionado: boolean;

  constructor(   private recaptchaV3Service: ReCaptchaV3Service,   public captchaSerice: RecaptchaService
  ) {
    this.robot = true;
    this.presionado = false;
  }

  ngOnInit(): void {
  }

  getInfoRecaptcha() {
    this.robot = true;
    this.presionado = true;
    this.recaptchaV3Service.execute('')
      .subscribe((token) => {
        const auxiliar = this.captchaSerice.getToken(token)
        if (  auxiliar.includes('true') ) {
          this.robot = false;
        }
      });
  }

Por último, modificamos la api para recibir la petición del front-end creando la siguiente ruta en el proyecto https://github.com/al118345/envio_email_api_python
class Verificar_Captcha(Resource):
        def post(self, token):
            recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify'
            recaptcha_secret_key = ''
            payload = {
                'secret': recaptcha_secret_key,
                'response': token,
                'remoteip': request.remote_addr,
            }
            response = requests.post(recaptcha_url, data=payload)
            result = response.json()
            return result.get('success', False)

local_resources = [
    (Verificar_Captcha, '/verificar/<string:token>/'),
]
Para terminar, en la web https://www.google.com/u/3/recaptcha/admin/ puedes consultar una vista como la siguiente imagen dónde puedes comprobar la cantidad de gente que ha realizado el login y la puntuación obtenida de media.

Ejemplo en ejecución

Ejemplo de ejecución XmlHttpRequest(síncrona) de google recaptcha

¿Eres un robot?. Según recaptcha de Google:

Eres un robot