Escolha uma Página
(Last Updated On: 10/01/2021)

O Captcha ajuda a evitar que robôs tentem invadir seus sites através de formulários, passando a ser mais uma pedra do caminho de invasões automatizadas. Quem tenta acessar o sistema usando o formulário passa a ter que também (pelo menos) clicar num botão dizendo: “Não sou um robô”.

O Google oferece esse serviço. Chamando-o de reCaptcha. Que pode ser usado com Core MVC.

Se você tiver algumas visualizações com entradas com acesso público, especialmente se forem servidas por meio do controlador com [AllowAnonymous], então provavelmente gostará de adicionar CAPTCHA a essas visualizações. Caso contrário, você sempre corre o risco de ser inundado por spam automatizado e até ser invadido.

Como todo serviço do Google, você precisar ter uma conta de Gmail para acessar o serviço em: https://www.google.com/recaptcha/admin

O site é bem confuso e muito pouco intuitivo. Você nunca sabe por onde começar. Se clicar no topo, vai ler:

O reCAPTCHA usa um mecanismo avançado de análise de risco e desafios adaptativos para impedir que o software malicioso se envolva em atividades abusivas no seu site. Enquanto isso, usuários legítimos poderão fazer login, fazer compras, visualizar páginas ou criar contas e usuários falsos serão bloqueados.

Tem de cllicar,esmo é no sinal de +, para adicionar a URL do seu site.

 

Coloque um nome para lembrar de que site é o reCaptcha, em etiqueta. Escolha a última versão: recaptcha v2. Defina o seu domínio. Importante: clique no botão de + depois que acrescentar seu domínio – e defina também localhost para depois poder testat o reCapcha na sua máquina local, ANTES de subir a sua aplicação para o servidor.

Duas dicas importantes:

  • Além de localhost, defina também 127.0.0.1 (verifique se o IIS do seu windows está ativado como um recurso do windows, se não estiver, ative);
  • Escolha a versão V2 do recapcha. Com a V3 não funcionou de jeito nenhum, nem na máquina local, nem remota,.

O proprietário aparece como seu e-mail do Gmail, mas você pode acrescentar outros (nunca tentei). Aceite os termos do serviço. Clique em enviar, no finalzinho da página.

Pronto, você tem agora os dados do seu recaptcha (sugiro guardar num arquivo txt, no seu micro).

Integração com Core Mvc

Para ter a possibilidade de usar o captcha em qualquer formulário, de qualquer página, é melhor chamar a API do Google do arquivo _layout.cshtml, em Views/Shared, uma linha acima de </head>. no topo da página.

 

chamada da API do Google em todas paginas no arquivo_layout.cshtml, em views/shared

    <link rel="stylesheet" href="~/css/site.css" />
    <script src="https://www.google.com/recaptcha/api.js"></script>
</head>
<body data-rsssl=1 data-rsssl=1 data-rsssl=1>

Outra possibilidade é colocar no final de cada View que terá o formulário com reCaptcha, no final da página, na section de script:

colocar em cada view com recaptcha no final da pagina
@section Scripts {
    <script src='https://www.google.com/recaptcha/api.js'></script>
}

Onde colocar o reCaptcha?

Em qualquer formuário que você quiser. Nas views, será necessário usar a “Chave do Site”, a site key que o Google nos forneceu. Calma, já veremos onde ela será guardada. No momento vamos assumir que ela está guardadinha em ViewBag,ChavedoSite.

Assim, em qualquer formulário onde você quiser usar o reCaptcha, vai ter de colocar antes de </form> o seguinte código:

Onde colocar o reCaptcha?

Em qualquer formuário que você quiser. Nas views, será necessário usar a “Chave do Site”, a site key que o Google nos forneceu. Calma, já veremos onde ela será guardada. No momento vamos assumir que ela está guardadinha em ViewBag.ChavedoSite.

Assim, em qualquer formulário onde você quiser usar o reCaptcha, vai ter de colocar antes de </form> o seguinte código:

linha a ser colocada antes de qualquer submit de formularios com reCaptcha
<div class="g-recapcha" data-siteky="@ViewBag.ChavedoSite">
</div>

Exemplo simplificado

Escolha qualquer formulário. Em geral o formulário está numa página de Create.cshtml se foi criado com scafolding, Neste caso, também deveria colocar o reCaptcha na página de edição, em geral Edit.cshtml.

exemplo simplificado para ser colocado nos formularios de criacao e edicao, Create.cshtml e Edit.cshtml
@model PoupaTempoDigital.Models.TP_BancosCaixas

@{
    ViewData["Title"] = "Cria Banco ou Caixa";
}

<h4>Cria Banco ou Caixa</h4>

<h5>Dados</h5>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="NomeBancoCaixa" class="control-label"></label>
                <input asp-for="NomeBancoCaixa" class="form-control" />
                <span asp-validation-for="NomeBancoCaixa" class="text-danger"></span>
              
        			<div class="g-recapcha" data-sitekey="@ViewBag.ChavedoSite">
</div>
              
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Onde guardar as chaves?

Eu proponho guardar no arquivo appsettings. json, no diretório raiz do site, assim:

chaves do google reCaptcha no appsettings.json
{
  "Email": {
    "FromName": "Site Poupatempo Digital",
    "FromAddress": "atendimento@poupatempodigital.com.br",
    "LocalDomain": "poupatempodigital.com.br",
    "MailServerAddress": "mail.poupatempodigital.com.br",
    "MailServerPort": "25", //SMTP Port:  25 "or" 8889:,
    "UserId": "atendimento@poupatempodigital.com.br",
    "UserPassword": "senha"
  },
  "Sendgrid": {
    "ApiKey": "apiso sendgrid"
  },
  "Twilio": {
    "accountSid": "sid",
    "authToken": "token",
    "whatsAppFrom": "whatsapp:xxxx" //número de saída Twilio
  },

  "reCaptcha": {
    "chaveDeSite": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "chaveSecreta": "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
  }
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Controladores

Sempre temos nos controladores um get (que chama o formulário para mostrar na tela) e um post (que recebe os dados do formulário quando você dá um SUBMIT).

No método do get precisamos passar o valor da chave do site, em data-siteky=”@ViewBag.ChavedoSite”

Podemos por no view da página uma ViewBag com a Mensagem de retorno, se quisermos, tendo algo assim: @ViewBag.MensagemDeRetorno:

<div class="alert alert-success" role="alert">
  @ViewBag.MensagemDeRetorno
</div>

Só que quando chamarmos pelo get, essa mensagem estará vazia. Podemos preparar a view para mostrá-la somente quando houver retorno pelo controlador POST.

ajuste o arquivo cshtml de edicao e ou criacao
     <div class="g-recaptcha" data-siteky="@ViewBag.ChavedoSite">
            </div>
            @if (@ViewBag.MensagemDeRetorno != "")
            {
            <div class="alert alert-success" role="alert">
                @ViewBag.MensagemDeRetorno
            </div>
            }
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>

GET

No get temos de pegar um valor que está em appsettings.json. Vamos precisar, no início do contrlador, definir _configuration.

rotina get do controlador de criacao (por exemplo, vale o mesmo para edicao)
  // GET: TP_BancosCaixas/Create
        public IActionResult Create()
        {
            //precisamos pegar o valor que está em Appsettings.json
            ViewBag.ChavedoSite = _configuration.GetSection("reCaptcha").GetSection("chaveDeSite").Value;
            ViewBag.MensagemDeRetorno = "";
            return View();
        }

No topo do arquivo acrescente:

using Microsoft.Extensions.Configuration;

Acrescente na chamada do controlador:

  • private readonly IConfiguration _configuration;
  • public PessoasController(ApplicationDbContext context,
    IConfiguration configuration)
  • _configuration = configuration;

Ficando algo assim:

 

rotina de inicio do controlador com as definicoes _configuration, para pegar os dados em appsettings.json
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using PoupaTempoDigital.Data;
using PoupaTempoDigital.Models;

namespace PoupaTempoDigital.Controllers
{
    [Authorize(Roles = Papeis.AdminEndUser)]
    [Authorize(Roles = Papeis.ColaboradorEndUser)]
    [Authorize(Roles = Papeis.ClienteEndUser)]
    public class TP_BancosCaixasController : Controller
    {
        private readonly ApplicationDbContext _context;
        private readonly IConfiguration _configuration;

        public TP_BancosCaixasController(ApplicationDbContext context
            ,IConfiguration configuration)

        {
            _context = context;
            _configuration = configuration;

        }

POST

 O post é mais chatinho. Tem que pessar para a API do Google as variáveis response e secret.

Acrescentar no topo da página: 

using System.Net;

using System.Net.Http; (provalmente vai ter que instalar no seu projeto)

using Newtonsoft.Json;

 

rotina POST do controlador
        // POST: TP_BancosCaixas/Create

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("IdBancoCaixa,IdUsuario,NomeBancoCaixa,NumeroBanco,NumeroConta,NumeroAgencia,SaldoInicial,DataSaldoInicial,TipoDeConta")] TP_BancosCaixas tP_BancosCaixas)
        {
            if (ModelState.IsValid)
            {
                HttpClient httpClient = new HttpClient();
                var response = Request.Form["g-recaptcha-response"]; // that's how you get it from the Request object
            
                string secretKey = _configuration.GetSection("reCaptcha").GetSection("chaveSecreta").Value;
                var cliente = new WebClient();
               // var res = httpClient.GetAsync($"https://www.google.com/recaptcha/api/siteverify?secret={secretKey}&response={response}").Result;
                var resultado = cliente.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secretKey, response));
                var obj = JObject.Parse(resultado);
                var status = (bool)obj.SelectToken("success");
                if (status)
                {
          					//acrescentar somente se o seu form voltar para a mesma página de entrada de dados
                    //ViewBag.MensagemDeRetorno = "Validação do Google reCaptcha feita com SUCESSO !!!";
                    _context.Add(tP_BancosCaixas);
                    await _context.SaveChangesAsync();
                    return RedirectToAction(nameof(Index));
                }
                else
                {
                    ViewBag.MensagemDeRetorno = "Validação do Google reCaptcha FALHOU !!!";
                    ViewBag.ChavedoSite = _configuration.GetSection("reCaptcha").GetSection("chaveDeSite").Value;
                    return View(tP_BancosCaixas);
                }



                }
            return View(tP_BancosCaixas);
        }