Come Implementare Cloudflare Turnstile Captcha in PHP

Come Implementare Cloudflare Turnstile Captcha in PHP

14 Gen. 2026

Perché Cloudflare Turnstile?

Quando ho iniziato a implementare la protezione dai bot per il mio ultimo progetto PHP, mi sono trovato di fronte a un ostacolo. La maggior parte delle soluzioni CAPTCHA frustrano gli utenti con puzzle impossibili da risolvere o hanno documentazioni complesse che presuppongono tu stia lavorando con un framework specifico. È stato allora che ho scoperto Cloudflare Turnstile e ho deciso di creare una guida di implementazione semplice e diretta.

Cloudflare Turnstile è un'alternativa user-friendly ai CAPTCHA tradizionali che non richiede agli utenti di risolvere puzzle, identificare semafori o decifrare testi distorti. Funziona silenziosamente in background, validando che i tuoi visitatori siano persone reali senza creare attriti nell'esperienza utente. Il bello è che non hai bisogno di instradare il tuo traffico attraverso Cloudflare per utilizzarlo.

Il Problema che Ho Incontrato

Sebbene la documentazione di Cloudflare sia completa, ho fatto fatica a trovare esempi semplici e indipendenti dal framework che mostrassero come validare le risposte di Turnstile lato server in PHP puro. La maggior parte dei tutorial si concentrava sull'implementazione JavaScript o richiedeva framework PHP specifici. Avevo bisogno di qualcosa di basilare che potessi adattare a qualsiasi progetto PHP.

Per questo motivo ho creato questo repository con esempi funzionanti che puoi copiare, incollare e personalizzare secondo le tue esigenze.

Come Iniziare: Prerequisiti

Prima di immergerti nel codice, dovrai configurare Cloudflare Turnstile e ottenere le tue chiavi API:

  1. Vai alla Dashboard di Cloudflare
  2. Naviga su Turnstile nel tuo account
  3. Crea un nuovo sito e registra il tuo dominio/hostname
  4. Riceverai due chiavi: 
    • Site Key: Utilizzata nel tuo HTML frontend
    • Secret Key: Utilizzata per la verifica lato server (mantienila al sicuro!)

Implementazione: Il Frontend

Innanzitutto, creiamo il form HTML con il widget Turnstile. È sorprendentemente semplice:

<!DOCTYPE html>
<html lang="it">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Esempio Cloudflare Turnstile</title>
    <!-- Carica lo Script Cloudflare Turnstile -->
    <script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
</head>
<body>
    <h1>Form di Contatto</h1>
    
    <form action="submit-example.php" method="POST">
        <label for="name">Nome:</label>
        <input type="text" id="name" name="name" required>
        
        <label for="email">Email:</label>
        <input type="email" id="email" name="email" required>
        
        <label for="message">Messaggio:</label>
        <textarea id="message" name="message" required></textarea>
        
        <!-- Widget Cloudflare Turnstile -->
        <div class="cf-turnstile" data-sitekey="TUA_SITE_KEY_QUI"></div>
        
        <button type="submit">Invia</button>
    </form>
</body>
</html>

Punti chiave:

  • Includi lo script Turnstile nella sezione <head>
  • Aggiungi il div cf-turnstile dove vuoi che appaia il widget
  • Sostituisci TUA_SITE_KEY_QUI con la tua Site Key effettiva

Il widget si renderizzerà automaticamente e gestirà la sfida. Quando il form viene inviato, Turnstile aggiunge un campo nascosto chiamato cf-turnstile-response contenente un token.

Validazione Lato Server: La Parte Importante

È qui che la maggior parte delle guide ti lascia a piedi. La validazione lato server è cruciale perché impedisce agli utenti malintenzionati di bypassare il CAPTCHA semplicemente inviando il form senza passare attraverso Turnstile.

<?php
// submit-example.php

// Controlla se il form è stato inviato
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    
    // Ottieni il token di risposta di Turnstile
    $turnstileResponse = $_POST['cf-turnstile-response'] ?? '';
    
    // La tua Secret Key da Cloudflare
    $secretKey = 'TUA_SECRET_KEY_QUI';
    
    // Endpoint di verifica Cloudflare Turnstile
    $verifyUrl = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
    
    // Prepara i dati per la verifica
    $data = [
        'secret' => $secretKey,
        'response' => $turnstileResponse,
        'remoteip' => $_SERVER['REMOTE_ADDR'] // Opzionale ma consigliato
    ];
    
    // Inizializza cURL
    $curl = curl_init();
    
    curl_setopt_array($curl, [
        CURLOPT_URL => $verifyUrl,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => http_build_query($data),
        CURLOPT_RETURNTRANSFER => true
    ]);
    
    // Esegui la richiesta
    $response = curl_exec($curl);
    $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    curl_close($curl);
    
    // Analizza la risposta JSON
    $result = json_decode($response, true);
    
    // Controlla se la verifica è stata positiva
    if ($httpCode === 200 && isset($result['success']) && $result['success'] === true) {
        // Verifica CAPTCHA superata!
        
        // Elabora i dati del form qui
        $name = htmlspecialchars($_POST['name']);
        $email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
        $message = htmlspecialchars($_POST['message']);
        
        // La tua logica di elaborazione del form
        echo "Grazie, " . $name . "! Il tuo messaggio è stato ricevuto.";
        
        // Invia email, salva nel database, ecc.
        
    } else {
        // Verifica CAPTCHA fallita
        
        $errorCodes = $result['error-codes'] ?? ['unknown-error'];
        echo "Verifica CAPTCHA fallita. Codici errore: " . implode(', ', $errorCodes);
        
        // Registra l'errore o reindirizza al form
    }
    
} else {
    // Gestisci richieste non-POST
    header('Location: form-example.php');
    exit;
}
?>

Comprendere il Flusso di Validazione

  1. Recupero Token: Quando un utente invia il form, Turnstile include automaticamente un token di risposta nel campo POST cf-turnstile-response
  2. Richiesta Server: Il tuo script PHP invia questo token, insieme alla tua Secret Key, all'endpoint di verifica di Cloudflare
  3. Verifica: Cloudflare valida il token e restituisce una risposta JSON che indica successo o fallimento
  4. Elaborazione: Solo se la verifica ha successo dovresti elaborare i dati del form

Codici di Errore Comuni

Turnstile può restituire codici di errore nella risposta. Ecco i più comuni:

  • missing-input-secret: Manca la chiave segreta
  • invalid-input-secret: La chiave segreta non è valida
  • missing-input-response: Manca il token di risposta
  • invalid-input-response: Il token di risposta non è valido o è scaduto
  • timeout-or-duplicate: Il token di risposta è già stato validato o è scaduto

Best Practice di Sicurezza

  1. Non esporre mai la tua Secret Key: Tienila in variabili d'ambiente o in un file di configurazione sicuro
  2. Valida sempre lato server: La validazione solo lato client può essere bypassata
  3. Includi l'IP remoto: Questo aiuta Cloudflare a rilevare pattern sospetti
  4. Gestisci gli errori con eleganza: Non rivelare troppe informazioni nei messaggi di errore
  5. Usa HTTPS: Utilizza sempre connessioni sicure quando trasmetti dati sensibili

Personalizzare il Widget

Turnstile supporta diverse opzioni di personalizzazione:

<div class="cf-turnstile" 
     data-sitekey="TUA_SITE_KEY_QUI"
     data-theme="light"
     data-size="normal"
     data-language="it">
</div>

Opzioni disponibili:

  • data-theme: "light", "dark" o "auto"
  • data-size: "normal" o "compact"
  • data-language: Qualsiasi codice lingua supportato
  • data-appearance: "always" o "interaction-only"

Perché Questo Approccio Funziona

Questa implementazione è intenzionalmente semplice e indipendente da framework. Utilizza solo:

  • PHP standard (nessun framework richiesto)
  • cURL per richieste HTTP (disponibile nella maggior parte delle installazioni PHP)
  • Gestione errori di base

Puoi facilmente integrare questo in:

  • Applicazioni PHP personalizzate
  • Siti WordPress (con modifiche minori)
  • Codebase legacy
  • Qualsiasi framework PHP (CodeIgniter, Laravel, Symfony, ecc.)

Testare la Tua Implementazione

Cloudflare fornisce chiavi di test che puoi usare durante lo sviluppo:

  • Site Key: 1x00000000000000000000AA (passa sempre)
  • Secret Key: 1x0000000000000000000000000000000AA (passa sempre)

Usa queste chiavi per testare la tua implementazione prima di distribuirla con chiavi reali.

Conclusione

Implementare Cloudflare Turnstile in PHP non deve essere complicato. Con questo approccio semplice e diretto, puoi aggiungere una protezione robusta dai bot ai tuoi form senza frustrare i tuoi utenti o perderti in documentazioni complesse.

Il codice completo e funzionante è disponibile nel mio repository GitHub, dove puoi trovare sia l'esempio del form che quello di submission pronti all'uso.

Se incontri problemi o hai domande, sentiti libero di aprire una issue su GitHub. Farò del mio meglio per aiutarti!

Risorse Correlate:

Altri articli: