Cloudflare Turnstile com HTML e PHP

O Turnstile oferece aos visitantes do site experiências na web livres de frustração e sem CAPTCHA, com apenas um trecho simples de código gratuito. Além disso, o Turnstile detém o abuso e confirma se os visitantes são reais sem causar preocupações de privacidade de dados e sem as desagradáveis UX que os CAPTCHAs impõem aos usuários. E é gratuito.

Abaixo eu demonstro uma função simples para quem quer instalar / usar a alternativa de CAPTCHA da Cloudflare, o Turnstile numa página em PHP. Fiz isso no infoaqui.com.br.


Como ativar o serviço na Cloudflare

Antes de qualquer coisa, você precisa ativar o serviço dentro de uma conta na Cloudflare. É simples. Veja abaixo:

  1. Crie uma conta na Cloudflate (ou acese a sua);
  2. Navegue até a guia “Turnstile” na barra de navegação;
  3. Cadastre o domínio do seu site para obter a chaves necessárias: do site e a secreta.

Depois de tudo cadastrado dentro da Cloudflare, vamos aos código necessários.

Instalando o Turnstile na página HTML e validado com PHP

Copie o HTML abaixo e cole dentro do HEAD da sua página:

<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>

Depois que o script for incorporado, você poderá usar a renderização implícita. Aqui, o HTML é verificado em busca de elementos que tenham uma classe cf-turnstile. Veja o exemplo de form:

<form action="/login" method="POST">  <div class="cf-turnstile" data-sitekey="Sua SiteKey"></div>  <input type="submit"></form>

Assim que um desafio for resolvido, um token é injetado em seu formulário, com o nome cf-turnstile-response. Esse token pode ser usado com o endpoint de siteverify para validar uma resposta de desafio. Um token só pode ser validado uma vez e um token não pode ser recuperado duas vezes. A validação pode ser feita no lado do servidor. Ai vem a função do PHP. No caso do infoaqui.com.br que foi desenvolvido em Laravel, montei o seguinte:

public static function testarCaptchaCloudflare($captcha){
        if(!empty($captcha)){
            $url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
            $curl = curl_init();
            curl_setopt_array($curl, [
                CURLOPT_URL => $url,
                CURLOPT_HTTPHEADER => [
                    'Content-Type: application/json',
                ],
                CURLOPT_CUSTOMREQUEST => 'POST',
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_FOLLOWLOCATION => 1,
                CURLOPT_CONNECTTIMEOUT => 10,
                CURLOPT_TIMEOUT => 30,
                CURLOPT_POSTFIELDS => json_encode([
                    'secret' => 'Sua SecretKey',
                    'response' => $captcha
                ]),
            ]);
            $result = curl_exec($curl);
            $err = curl_error($curl);
            curl_close($curl);
            if ($json = json_decode($result)) {
                if ($json->success) {
                    return [
                        'status' => 1,
                    ];
                }
                return [
                    'status' => 0,
                    'turnstile_response' => $json,
                ];
            }
            return [
                'status' => 0,
                'error' => 'Unknown error occured'
            ];
        }else{
            return [
                'status' => 0,
                'error' => 'Token captcha is empty'
            ];
        }
     } 

Pronto! Depois de submeter o formulário de login com o captcha por método post, além dos campos do formulário, foi inserido também um campo cf-turnstile-response. No meu caso testei o retorno da seguinte forma:

$captchaCloudflare = $request->get('cf-turnstile-response');
if(static::testarCaptchaCloudflare($captchaCloudflare)['status'] == True)
{
......conteúdo caso o teste seja positivo......
}else{
......conteúdo caso o teste seja negativo...... 
}

Saiba mais sobre o Turnstile no blog da Cloudflare.