Conectando o Google reCAPTCHA ao Vue e validando a resposta no servidor


Neste artigo, mostrarei como conectar o captcha do Google (reCAPTCHA) ao Vue JS e validar a resposta no servidor (uso o back-end no Laravel / Lumen como exemplo, mas o princípio da validação é o mesmo para todas as tecnologias).


Prefácio


Usaremos o reCAPTCHA invisível .
Este é um captcha * invisível, que não precisa ser passado até que o sistema considere necessário. O administrador do site pode definir um nível limite (preferência de segurança) no qual o sistema exigirá que o usuário seja submetido a uma verificação adicional.


* - o ícone reCAPTCHA ainda deve estar presente na página.



Captcha invisível no site.


Pergunta / Resposta


Antes de começar o trabalho, gostaria de responder às perguntas que surgiram quando comecei a trabalhar com o Google reCAPTCHA.


P: Quanto custa o reCAPTCHA?
R: O ReCAPTCHA do Google é uma ferramenta gratuita.


P: Por que preciso verificar novamente a resposta do usuário no back-end se ele já passou o captcha no site?
R: Quando você faz uma solicitação ao servidor, envia algo assim:


POST /register 1.1 HTTP Host: www.example.com { "email:"user@gmail.com", "password": "supersecret", "recaptcha-token":"01ASJASJFZ_AASD3115..." } 

Se você não verificar o token captcha no back-end, os bots podem simplesmente enviar spam com solicitações SEM esse token ou substituí-lo por um fictício.


P: Eu tenho uma reação, o que devo fazer?
A: Reagir JS é uma grande coisa. Se você usá-lo para o desenvolvimento de sites, aconselho a prestar atenção em https://github.com/appleboy/react-recaptcha . O princípio de operação é muito semelhante ao exemplo do Vue.


Começando a trabalhar


Portanto, antes de começarmos a cozinhar, precisamos de uma lista de ingredientes:



Etapa 1: obtenha as chaves para usar o reCAPTCHA no seu site


Precisamos obter a chave do site e a chave secreta no site do Google: https://www.google.com/recaptcha/admin#list



Você pode escrever qualquer coisa no campo do rótulo.


Em seguida, selecione o tipo - Crachá invisível do reCAPTCHA .


Você pode especificar vários domínios nos quais você usará o captcha.
Como exemplo, eu indiquei yourawesomedomain.com e localhost .


Aceitamos os termos de uso e seguimos em frente.



Você recebeu duas chaves, mantenha-as em um local seguro. Voltaremos a eles mais tarde.


Etapa 2: Frontend. Instalando e conectando o captcha aos nossos formulários


Para começar, precisamos adicionar este código à seção principal:


 <script src="https://www.google.com/recaptcha/api.js?onload=vueRecaptchaApiLoaded&render=explicit" async defer></script> 

A propriedade onload informará nosso componente que o captcha está pronto para uso.


A seguir, mostrarei o componente acabado e o analisaremos em partes:


 <template> <div id="app"> <div class="container my-4"> <div class="row justify-content-center"> <div class="col-md-8"> <h2 class="text-center mb-4"> Sign Up Form with Google reCAPTCHA </h2> <form method="post" @submit.prevent="validate"> <div class="form-group"> <input type="email" name="email" class="form-control" placeholder="Enter your e-mail address" required /> </div> <div class="form-group"> <input type="password" name="password" class="form-control" placeholder="Enter your password" required /> </div> <div class="form-group"> <vue-recaptcha ref="recaptcha" size="invisible" :sitekey="sitekey" @verify="register" @expired="onCaptchaExpired" /> <button type="submit" class="btn btn-primary btn-block"> Sign Up </button> </div> </form> </div> </div> </div> </div> </template> <script> import VueRecaptcha from 'vue-recaptcha' export default { name: 'Register', components: { VueRecaptcha }, data () { return { email: null, password: null, sitekey: ' SITE KEY' } }, methods: { register (recaptchaToken) { axios.post('https://yourserverurl.com/register', { email: this.email, password: this.password, recaptchaToken: recaptchaToken }) }, validate () { //       // ,   vee validate //       ,   this.$refs.recaptcha.execute() }, onCaptchaExpired () { this.$refs.recaptcha.reset() } } } </script> 

Exemplo de componente Usando VeeValidate para validar campos
 <template> <div id="app"> <div class="container my-4"> <div class="row justify-content-center"> <div class="col-md-8"> <h2 class="text-center mb-4"> Sign Up Form with Google reCAPTCHA </h2> <form method="post" @submit.prevent="validate"> <div class="form-group"> <input type="email" name="email" class="form-control" placeholder="Enter your e-mail address" v-validate.disable="'required|email'" required /> <div v-show="errors.has('email')" class="invalid-feedback d-block" > {{ errors.first('email') }} </div> </div> <div class="form-group"> <input type="password" name="password" class="form-control" placeholder="Enter your password" v-validate.disable="'required|min:6|max:32'" required /> <div v-show="errors.has('password')" class="invalid-feedback d-block" > {{ errors.first('password') }} </div> </div> <div class="form-group"> <vue-recaptcha ref="recaptcha" size="invisible" :sitekey="sitekey" @verify="register" @expired="onCaptchaExpired" /> <button type="submit" class="btn btn-primary btn-block"> Sign Up </button> </div> </form> </div> </div> </div> </div> </template> <script> import VueRecaptcha from 'vue-recaptcha' export default { name: 'Register', components: { VueRecaptcha }, data () { return { email: null, password: null, sitekey: ' SITE KEY' } }, methods: { register (recaptchaToken) { axios.post('https://yourserverurl.com/register', { email: this.email, password: this.password, recaptchaToken: recaptchaToken }) }, validate () { const self = this self.$validator.validateAll().then((result) => { if (result) { self.$refs.recaptcha.execute() } }) }, onCaptchaExpired () { this.$refs.recaptcha.reset() } } } </script> 

Para começar, importamos o Vue-Recaptcha para o nosso componente:


 import VueRecaptcha from 'vue-recaptcha' ... components: { VueRecaptcha }, 

Em seguida, declaramos a propriedade sitekey no componente data ():


 data () { return { ... sitekey: ' SITE KEY' } }, 

Adicione o componente Vue-Recaptcha ao nosso formulário:


 <vue-recaptcha ref="recaptcha" size="invisible" :sitekey="sitekey" @verify="register" @expired="onCaptchaExpired" /> 

O método de registro será chamado após a conclusão bem-sucedida do captcha, enquanto expirado será chamado após a expiração do captcha.


O método onCaptchaExpired reinicia o captcha:


 onCaptchaExpired () { this.$refs.recaptcha.reset() } 

No próprio formulário, adicionamos o evento @ submit.prevent = "validate" , que aciona o método validate quando o formulário é enviado .


 validate () { this.$refs.recaptcha.execute() } 

O processo pode ser descrito da seguinte maneira:


  1. O usuário inseriu os dados e clicou no botão Inscrever-se, a função validate () é chamada.
  2. A função validate () inicia o captcha; se o usuário o passar com êxito, o método de registro será chamado.

No método de registro, obtemos um recaptchaToken , que devemos enviar ao servidor junto com os dados que o usuário digitou:


 register (recaptchaToken) { axios.post('https://yourserverurl.com/register', { email: this.email, password: this.password, recaptchaToken: recaptchaToken }) } 

Nisso, nosso trabalho com o front-end está concluído. ReCAPTCHA instalado e funcionando com sucesso.


PS Se você usar o captcha em vários componentes, é melhor colocar o sitekey no arquivo .env e obtê-lo usando process.env :


 data () { return { ... sitekey: process.env.VUE_APP_RECAPTCHA_TOKEN } }, 

Etapa 3: validação de back-end. Exemplo de validação no Laravel e Lumen


Fazer a validação da resposta no servidor é muito simples. Vamos começar com o exemplo do Laravel.


1) Na pasta config , crie um arquivo recaptcha.php com o seguinte conteúdo:


 <?php return [ 'enabled' => env('RECAPTCHA_ENABLED', true), 'key' => env('RECAPTCHA_SITE_KEY'), 'secret' => env('RECAPTCHA_SECRET_KEY'), ]; 

2) Depois disso, adicione as variáveis ​​ao arquivo .env :


 RECAPTCHA_ENABLED=FALSE RECAPTCHA_SITE_KEY=_SITE_KEY RECAPTCHA_SECRET_KEY=_SECRET_KEY 

3) Instale o GuzzleHttp para poder enviar solicitações da API do Google:


 composer require guzzlehttp/guzzle 

4) No controlador, adicione o método checkRecaptcha :


 protected function checkRecaptcha($token, $ip) { $response = (new Client)->post('https://www.google.com/recaptcha/api/siteverify', [ 'form_params' => [ 'secret' => config('recaptcha.secret'), 'response' => $token, 'remoteip' => $ip, ], ]); $response = json_decode((string)$response->getBody(), true); return $response['success']; } 

Nesse método, enviamos nosso token (que recebemos do front-end) usando o método POST para https://www.google.com/recaptcha/api/siteverify


5) No método de registro (no seu caso, o nome pode ser diferente, este é o método para o qual você enviou a solicitação POST do front-end), adicione o seguinte código:


 if (config('recaptcha.enabled') && !$this->checkRecaptcha($request->recaptcha_token, $request->ip())) { return return response()->json([ 'error' => 'Captcha is invalid.', ], Response::HTTP_BAD_REQUEST); } 

Está tudo pronto para usar!


  • Ao acessar o método de registro, recebemos email, senha e recaptcha_token.
  • Se recaptcha estiver ativado (no arquivo .env, o valor RECAPTCHA_ENABLED é TRUE),
    O Laravel enviará uma solicitação de API do Google.
  • Se a resposta for não, retornamos um erro com o texto: Captcha é inválido.
  • Se positivo, continue o registro do usuário.


Token Travel Apresentação visual.


O código completo do controlador ficará assim:


 <?php namespace App\Http\Controllers\Users; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Illuminate\Http\Response; use GuzzleHttp\Client; class UserController extends Controller { protected function checkRecaptcha($token, $ip) { $response = (new Client)->post('https://www.google.com/recaptcha/api/siteverify', [ 'form_params' => [ 'secret' => config('recaptcha.secret'), 'response' => $token, 'remoteip' => $ip, ], ]); $response = json_decode((string)$response->getBody(), true); return $response['success']; } public function register(Request $request) { $request->validate([ 'email' => 'required|string|email|unique:users|max:255', 'password' => 'required|string|max:32|min:6', 'recaptcha_token' => 'string' ]); if (config('recaptcha.enabled') && !$this->checkRecaptcha($request->recaptcha_token, $request->ip())) { return response()->json([ 'error' => 'Captcha is invalid.', ], Response::HTTP_BAD_REQUEST); } //  .  ... } } 

Validação da resposta ao Lumen


No Lumen, fazemos tudo da mesma maneira que no exemplo do Laravel, exceto que precisamos registrar nossa configuração ( recaptcha.php ) no bootstrap / app.php :


 $app->configure('recaptcha'); 

Conclusão


Portanto, neste artigo, você aprendeu como usar o Google reCAPTCHA em seu projeto Vue.


ReCAPTCHA é uma ótima ferramenta gratuita para proteger seus recursos de bots.
Com o captcha invisível, você pode verificar os visitantes sem exigir que eles tomem alguma ação.


Exemplo de aplicação de um artigo no codepen


Fontes utilizadas:


  1. https://github.com/DanSnow/vue-recaptcha
  2. https://developers.google.com/recaptcha/docs/invisible
  3. https://developers.google.com/recaptcha/docs/verify
  4. https://security.stackexchange.com/questions/78807/how-does-googles-no-captcha-recaptcha-work

Source: https://habr.com/ru/post/pt443370/


All Articles