reCAPTCHA V3 – Protendo formulários contra bots/spam
Captchas são um tormento, sendo sincero ninguém gosta deles, mas se é ruim com eles pior sem eles. Se você por exemplo já teve um simples formulário de contato e seu site e ele teve alguma visibilidade deve ter recebido muito spam, superando em muito os contatos genuínos.
Para evitar que os formulário sejam alvo fácil de bots de spam podemos colocar um captcha, que em um passado muito distante vimos como fazer um exemplo muito simples, hoje em dia temos soluções melhores como o reCAPTCHA do Goggle.

Ele é relativamente simples de colocar em funcionamento e na versão atual(reCAPTCHA V3) não é mais necessário clicar em nada, o Google utiliza um mecanismo de análise de riscos para saber se quem está acessando a página é um bot ou um usuário real, fornecendo um score da certeza se quem está acessando é um bot ou uma pessoa.
Inserindo o reCAPTCHA
Para utilizar o reCAPTCHA primeiro precisaremos de uma chave da API, isso pode ser feito acessando https://www.google.com/recaptcha/admin, uma vez logado, irá pedir para registrar um novo site, segue abaixo a tela.
Marque a opção reCAPTCHA V3 no Tipo, adicione o domínio em que você vai inserir o captcha.
Após o cadastro você será redirecionado para a página exibindo as as chaves que são duas:
Note que uma chave será colocado no lado do cliente( chave do site ) e outra no lado do servidor(chave secreta).
Vamos agora então ao código do cliente:
<script src="https://www.google.com/recaptcha/api.js?render=chave_do_site"></script>
<script>
grecaptcha.ready(function() {
grecaptcha.execute('chave_do_site', {action: 'homepage'}).then(function(token) {
console.log(token);
});
});
</script>
No código devemos colocar a chave da API que geramos tanto na linha 1 como na linha 4. Outra configuração é a action
, nela colocamos qual é ação que iremos rastrear, fornecendo assim um detalhamento maior das principais ações rastreadas no painel administrativo.
O reCAPTCHA ao executar fornece um token
que deve ser utilizado para enviar para o servidor, isto pode ser feito com um campo oculto do formulário(<input type="hidden">
) ou através de uma requisição AJAX.
Vamos ao um pequeno exemplo com o hidden.
<form method="POST" action="processar.php">
<div>
<label for="nome">Nome:</label>
<input type="text" name="nome" id="nome" class="form-control">
</div>
<input type="hidden" name="recaptcha_token" id="recaptcha_token">
<div class="mt-4">
<input type="submit" value="Cadastrar" class="btn btn-primary">
</div>
</form>
<script src="https://www.google.com/recaptcha/api.js?render=chave_do_site"></script>
<script>
grecaptcha.ready(function() {
grecaptcha.execute('chave_do_site', {action: 'cadastro'}).then(function(token) {
document.querySelector("#recaptcha_token").value = token;
});
});
</script>
Na linha 6 criamos um campo oculto com id #recaptcha_token
, este campo será preenchido com o token quando o código do reCAPTCHA for executado e chamar a função passando o token na linha 16. Então na linha 17 pegamos o campo oculto(hidden) e colocamos o token como seu valor para ser passado para o script do lado do servidor.
No lado do servidor
Para verificar o token no lado do servidor vamos utilizar PHP, o Google fornece uma biblioteca muito fácil para fazer isso. Podemos carrega-la usando o composer. Para adicionar a biblioteca ao projeto utilize o comando abaixo:
composer require google/recaptcha "^1.2"
ou adicione a dependência diretamente ao composer.json
"require": {
"google/recaptcha": "^1.2"
}
Agora vamos ao código PHP
require_once 'vendor/autoload.php';
$secret = "chave_secreta";
$recaptcha = new \ReCaptcha\ReCaptcha($secret);
$remote_ip = $_SERVER["REMOTE_ADDR"];
$g_recaptcha_response = $_POST["recaptcha_token"];
$resposta = $recaptcha->verify($g_recaptcha_response, $remote_ip);
if ($resposta->isSuccess()) {
echo $respota->getHostname() . '<br>';
echo $respota->getScore() . '<br>';
echo $respota->getAction() . '<br>';
} else {
$errors = $resposta->getErrorCodes();
print_r($errors);
}
Na linha 1 carregamos a o autoload.php
do composer, na linha 2 guardamos em uma variável a chave secreta que obtemos no registro que fizemos no inicio. Na linha 3 criamos um objeto do reCAPTCH, que iremos utilizar para realizar a verificação.
Na linha 5 pegamos o ip do cliente e na linha 6 o token que mandamos através do campo oculto do formulário que configuramos acima. Este dados serão utilizados na linha 8 como parâmetro para o método verify
que irá retornar um objetos com os dados de análises.
O objeto $resposta
possui um método isSuccess()
que retorna true se análise detectou que não era um bot e false se era. O objeto também possui alguns métodos como getHostname()
que retorna o nome do domínio, getScore()
que retorna o score atribuído pelo mecanismo de análise sendo 1.0 como muito provavelmente um usuário real e 0 muito provavelmente um bot. O getAction()
retorna a ação que se está rastreando.
Se o método isSuccess()
retornar false podemos pegar os erros através de seus código pelos método getErrorCodes()
, segue abaixo a tabela de erros:
Código de Erro | Descrição |
missing-input-secret | O parâmetro secret está faltando |
invalid-input-secret | O parâmetro secret é inválido ou mal-formado |
missing-input-response | O parâmetro de resposta está faltando |
invalid-input-response | O parâmetro de resposta é inválido ou mal-formado |
bad-request | A requisição é inválida ou mal-formada |
timeout-or-duplicate | A resposta não é mais válida: é muito antiga ou ou foi utilizada de forma provisória |
Para aumentar a segurança podemos utilizar alguns métodos do objeto $recaptcha
que podem ser chamados em cadeia:
setExpectedHostname($hostname)
: garante que o hostname corresponda ao esperado. Você precisa dele se desabilitou a opção “Verificar a origem das soluções reCAPTCHA” nas suas credenciais.setExpectedAction($action)
: garante que a action corresponda ao esperado.( para a API v3) .setScoreThreshold($threshold)
: define um limite para o score para as respostas da API v3.setChallengeTimeout($timeoutSeconds)
: define um timeout entre o usuário que requisita e o servidor que o processa.
Um exemplo de uso ficaria mais ou menos assim:
require_once 'vendor/autoload.php';
$secret = "6Lfr0OcUAAAAACTopy7iaYjz9HO_z6a2UKn3Wx0H";
$recaptcha = new \ReCaptcha\ReCaptcha($secret);
$remote_ip = $_SERVER["REMOTE_ADDR"];
$g_recaptcha_response = $_POST["recaptcha_token"];
$resposta = $recaptcha
->setExpectedHostname('botecodigital.info')
->setExpectedAction('cadastro')
->setScoreThreshold(0.7)
->setChallengeTimeout(5*60)
->verify($g_recaptcha_response, $remote_ip);
Para ver um exemplo funcionando clique aqui,
Era isso espero que ajude. Até a próxima. 🙂