Programação PHP

hCaptcha com PHP

Protegendo formulário de seu site contra spam/bots com hCaptcha

avatar
Thiago Bomfim
18/07/2025 18h49
blog-img

O hCaptcha é uma ferramenta que auxilia serviços online a se proteger contra ataques de bots, spam e outros abusos. Nesse artigo, implementaremos o hCaptcha com PHP num formulário de login como exemplo.

Há alguns programas de computadores (bots) construídos para atacar sites. Esse ataques tem como principais objetivos enviar spam, invadir alguma conta ou indisponibilizar algum serviço do seu site. Nesse contexto, podemos utilizar o CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) para criar uma camada de segurança no site. O CAPTCHA consiste em criar um desafio capaz de distinguir se o serviço do site está sendo requisitado por um ser humano ou um bot.

O hCapctha é um dos serviços que permite que essa camada de segurança seja implementada no site, realizando perguntas que facilmente são interpretadas por ser humanos, mas difíceis para um bot.

Vâmos implementar o hCaptcha num formulário de login como exemplo. Antes de começar a implementação, verifique se seu ambiente de desenvolvimento atendem aos seguintes requisitos:

  1. necessário que o PHP esteja instalado em seu computador;
  2. ajustar seu host domínio no localhost: https://docs.hcaptcha.com/#local-development;
    1. Por aqui, ajustei meu domínio em /etc/hosts com 127.0.0.1 tutorials.local

 

No Frontend, utilizaremos o template formulário de login Bootstrap (https://getbootstrap.com/docs/5.3/examples/sign-in/). Crie um diretório chamado tutorials, e dentro deste diretório, crie outro diretório chamado captcha-com-php. Dentro do diretório captcha-com-phpcrie um arquivo html index.html com o conteúdo html extraído do template Bootstrap. Substitua a tag <main> pelo conteúdo abaixo:

 

<main class="form-signin w-100 m-auto">
       <div class="ajax_response pb-4"></div>       
       <form id="login" action="./hcaptcha-com-php/login.php" method="POST">
           <h1 class="h3 mb-3 fw-normal">Login</h1>
           <div class="form-floating">
               <input type="email" class="form-control" id="floatingInput" placeholder="Digite  seu email" name="email">
               <label for="floatingInput">Email</label>
           </div>
           <div class="form-floating">
               <input type="password" class="form-control" id="floatingPassword" placeholder="Digite a Senha" name="pwd">
               <label for="floatingPassword">Senha</label>
           </div>
           <div class="h-captcha" data-sitekey="your_site_key"></div>
           <button class="btn btn-primary w-100 py-2" type="submit">Entrar</button>
       </form>
   </main>
   <script src="https://js.hcaptcha.com/1/api.js?hl=pt" async defer></script>

 

É necessário incluir o recurso JavaScript hCaptcha em algum lugar da index.html, observe que eu incluí-o logo após a tag <main>, configurada para a linguagem Português (hl=pt):

<script src="https://js.hcaptcha.com/1/api.js?hl=pt" async defer></script>

Também inserir uma seção na qual o html hCaptcha será renderizada:

<div class="h-captcha" data-sitekey="your_site_key"></div>

No atributo data-sitekey="your_site_key" deve ser inserido sua chave configurada no cadastro em captcha.

Agora, dentro do diretório tutorials criado anteriormente, rode um servidor PHP pelo terminal com o seguinte comando: sudo php -S 127.0.0.1:80

Esse comando permite que um servidor Web seja ativado na porta 80, e nosso domínio configurado será direcionado para essa porta, assim podemos rodar os projetos dentro do diretório tutorials. No nosso ambiente de desenvolvimenmto a url http://tutorials.local/hcaptcha-com-php/ já possibilita executar a página index.html.

 

Agora implementaremos uma chamada JavaScript para quando o botão Entrar for clicado. Insira no fina da tag </body> o seguinte trecho de código JavaScript:

<script>

        const getAjaxRequest = () => {
            var Ajax;
            if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
                Ajax = new XMLHttpRequest();
            } else {// code for IE6, IE5
                Ajax = new ActiveXObject("Microsoft.XMLHTTP");
            }

            return Ajax;
        }

        const checkCaptcha = (form) => {
            var captchaResponse = form.elements['h-captcha-response'].value;
            return captchaResponse ? true : false;
        }

        var form = document.getElementById('login');
        form.addEventListener("submit", (event) => {
            event.preventDefault();
            
            var ajaxResponseMessage = document.querySelector('.ajax_response');

			var captcha = checkCaptcha(form);
			if (!captcha) {
				ajaxResponseMessage.innerHTML = 'Verifique se você é humano.';
				return;
			}

            var request = getAjaxRequest();

            var formData = new FormData(form);
			var AjaxContact = getAjaxRequest();
			AjaxContact.open('POST', form.action, true);
			AjaxContact.send(formData);
			AjaxContact.onreadystatechange = () => {

				if (AjaxContact.readyState == 4 && AjaxContact.status == 200) {            
					var response = JSON.parse(AjaxContact.responseText);			

					ajaxResponseMessage.innerHTML = response.message;

					if (response.status == 'SUCCESS') {
						form.reset();
					}

					if (response.status == 'DATA_FAIL') {
					}
				}					
			};

        });
    </script>

 

Esse trecho de código JavaScript é responsável por processar uma Request para o arquivo ./login.php que inserimos na action do formulário. Em instantes criaremos esse arquivo. Não se preocupe por agora em entender o código JavaScript, podemos em outro momento produzirmos um tutorial de chamada JavaScript Ajax.

Podemos agora criar o script que vai processar a Request oriundo do formulário da página de index.html. No diretório captcha-com-php, crie um arquivo login.php, que será responsável por processar a Request, validando se o token no desafio hcaptcha é realmente válido.

<?php

try {
    $check = checkRequest($_POST);
    if (!$check) {
        return;
    }
    $verify = curl_init();

    $checkCaptcha = (new HCaptcha())->verify($_POST['h-captcha-response']);
    if ($checkCaptcha) { // aqui pode prosseguir com a validação de email e senha
        jsonResponse(['status' => 'SUCSESS', 'message' => 'Login realizado com sucesso.']);
        return;
    } else {
        jsonResponse(['status' => 'DATA_FAIL', 'message' => 'Falha nos dados, recarregue a página e tente novamente.']);
        return;
    }
} catch (\Throwable $th) {
    jsonResponse(['status' => 'DATA_FAIL', 'message' => $th->getMessage()]);
    return;
}

function jsonResponse(array $dataResponse): void {
    echo json_encode($dataResponse);
}

function checkRequest(array &$request): bool {
    if (empty($request['email']) || empty($request['pwd'])) {
        jsonResponse(['status' => 'DATA_FAIL', 'message' => 'Preencha os campos.']);
        return false;
    }

    if (empty($request['h-captcha-response'])) {
        jsonResponse(['status' => 'DATA_FAIL', 'message' => 'Erro ao enviar, favor check se você é humano']);
        return false;
    }

    return true;
}

class HCaptcha
{
    private string $apiURL = 'https://api.hcaptcha.com/siteverify';
    private string $secret = 'YOUR-SECRET'; // YOUR-SECRET é obtido no seu cadastro


    public function __construct() {
    }

    public function verify(string $codeResponse): bool
    {
        $data = array(
            'secret' => $this->secret,
            'response' => $codeResponse,
            'remoteip' => $_SERVER['REMOTE_ADDR']
        );
        $verify = curl_init();
        curl_setopt($verify, CURLOPT_URL, $this->apiURL);
        curl_setopt($verify, CURLOPT_POST, true);
        curl_setopt($verify, CURLOPT_POSTFIELDS, http_build_query($data));
        curl_setopt($verify, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($verify);
        
        $responseData = json_decode($response);
        if($responseData->success) {
            return true;
        }

        return false;
    }
}

Quando no Frontend o desafio é processado, é criado no formulário um input chamado h-captcha-response com um token que é utilizado na API hCaptcha para validar o desafio. Nesse fluxo, é necessário inserir sua chave em YOUR-SECRET obtida no cadastro hCaptcha.

Temos uma Classe HCaptcha responsável por processar a validação por meio da API hCaptcha https://api.hcaptcha.com/siteverify, que deve ser requisitada num HTTP POST. Em caso de sucesso na resposta, prosseguimos com o fluxo, caso contrário, o fluxo é interrompido.

Vejamos como ficou a renderização do desafio:

 

Vejamos como ficou o fluxo realizado com sucesso:

 

 

A implementação pode ser aplicada num projeto MVC (Model-View-Controller).

O código está disponível no GitHub aqui

 

Conclusão

Os ataques à sites ocorrem e é inevitável. Para proteger seu site é necessário implantar camadas de seguranças nos fluxos de requisições do site para detectar possíveis ataques e bloquear. O hCaptcha é uma dessas camadas, que cria mecanismos para distinguir humanos de bots nos formulários.


Fontes:

Compartilhe com a galera \o/

Artigos relacionados

Vamos ficar em contato

Receba novidades, fique atualizado e ofertas especiais

Assine agora e receba newsletter semanal com materiais educacionais, novos cursos, postagens interessantes, livros populares e muito mais!