Realizzare un sistema CAPTCHA con PHP

27 ottobre 2017

CAPTCHA (completely automated public Turing test to tell computers and humans apart) è un sistema per determinare se l'utente che sta compiendo una determinata operazione sia umano e non un computer.

In questa lezione vedremo come realizzare un semplice sistema CAPTCHA da integrare nelle nostre pagine Web. L'esempio che anremo a costruire partirà da una form di contatto con i campi:

  • nome
  • cognome
  • messaggio
  • pulsante di submit

Il codice di partenza del nostro file index.php è:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Captcha Example</title>
    </head>
    <body>
        <form action="submit.php" method="post">
            <label>First Name <input type="text" name="firstName" /></label><br>
            <label>Last Name <input type="text" name="lastName" /></label><br>
            <label>Message <textarea name="message"></textarea></label><br>

            <input type="submit" name="submit">
        </form>
    </body>
</html>

L’'immagine CAPTCHA

Prima di integrare l'immagine all'interno del nostro form andiamo a scrivere il codice necessario alla sua generazione. Creiamo un nuovo file captcha.php ed inseriamo il codice per creare il background dell'immagine:

<?php

//creazione dell'immagine e aggiunta di un background di colore grigio
$image = imagecreatetruecolor(120, 30);
$background = imagecolorallocate($image, 200, 200, 200);
imagefill($image, 0, 0, $background);

Una volta realizzata la base andiamo ad inserire delle linee di disturbo per evitare che un bot (uno script programmato per compilare automaticamente i form) possa riconoscere facilmente il CAPTCHA:

$linesColor = imagecolorallocate($image, 100, 100, 100);
for ($i=1; $i<=5; $i++) {
   imagesetthickness($image, rand(1,2));
   imageline($image, 0, rand(0,30), 120, rand(0,30), $linesColor);
}

Per disegnare delle linee di disturbo utilizziamo un ciclo for ripetuto 5 volte. Ad ogni ciclo viene settata una larghezza della linea con un valore randomico compreso tra 1 o 2.

La funzione rand($min, $max) restituisce un valore randomico compreso tra i due parametri $min e $max.

Una volta determinata la larghezza della linea andremo a disegnarla con la funzione imageline() che prende in ingresso i seguenti parametri:

  • la risorsa di tipo immagine
  • la coordinata X di partenza
  • la coordinata Y di partenza
  • la coordinata X di arrivo
  • la coordinata Y di arrivo
  • il colore

Nel nostro esempio i valori di X sono fissi e sono composti dal punto 0 e dal punto 120 sull'asse delle X. 120 è il valore della larghezza della nostra immagine, in questo modo stiamo dicendo che le linee attraverseranno tutta l'immagine orizzontalmente. I due valori di Y, invece, vengono generati randomicamente con valori compresi tra 0 e la larghezza dell'immagine.

A questo punto andiamo a creare la stringa che contiene le cifre del CAPTCHA:

$captcha = '';
$textColor = imagecolorallocate($image, 0, 0, 0);
for ($x = 15; $x <= 95; $x += 20) {
    $value = rand(0, 9);
    imagechar($image, rand(3, 5), $x, rand(2, 14), $value, $textColor);

    $captcha .= $value;
}

Anche in questo caso eseguiamo un ciclo, la differenza è che quest’ultimo incrementa di 20 punti la posizione della cifra sull'asse delle X. In altre parole disegneremo le cifre in modo che abbiano una posizione casuale sull'asse delle Y e 20 punti di distanza una dall'altra sull'asse delle X. Ad ogni ciclo generiamo la cifra in maniera randomica ($value) e la concateniamo al CAPTCHA finale ($captcha).

Possiamo ora restituire l'immagine in formato PNG ed inserirla all'interno del form. Nel file captcha.php aggiungiamo:

header('Content-type: image/png');
imagepng($image);
imagedestroy($image);

In index.php, prima del pulsante, di submit inseriamo:

<p><img src="./captcha.php" /></p>
<label>CAPTCHA <input type="text" name="captcha" /><br><br>

Ricaricando index.php nel browser dovremmo vedere un risultato simile all'immagine seguente:

Figura 1. Immagine CAPTCHA.

Immagine CAPTCHA

Gestire il valore del CAPTCHA in sessione

Ora che abbiamo generato l'immagine dobbiamo memorizzare in sessione il valore della variabile $captcha in modo da poter verificare che il valore immesso dall'utente sia corretto.

Abbiamo già affrontato le sessioni in una lezione precedente. Il primo step da eseguire è inizializzare la sessione nel file captcha.php. Inseriamo quindi come prima riga del file:

<?php

session_start();

A questo punto dobbiamo salvare in sessione il valore generato dal CAPTCHA all'interno dell'immagine. Nel file captcha.php, una volta generata la stringa casuale, aggiungeremo:

$_SESSION['captcha'] = $captcha;

In questo modo all'interno dell'array con le informazioni della sessione ci sarà anche il valore da verificare al submit del form.

Verificare che il CAPTCHA sia valido

Una volta memorizzato il valore in sessione possiamo gestire il submit del form e il controllo di validità del codice. Andiamo quindi a creare il file submit.php che conterrà il codice di gestione del form:

<?php

session_start();

//se accediamo al file senza eseguire il submit della form
if (!isset($_POST['submit'])) {
    die('I dati non sono validi');
}

if ($_POST['captcha'] != $_SESSION['captcha']) {
    die('Codice non valido');
}

echo 'Codice valido.';

Il codice verifica che il valore inviato del CAPTCHA corrisponda a quello in sessione. In caso negativo termina l'esecuzione dello script con un errore, altrimenti si può procedere con l'invio della mail.

Il file submit.php viene richiamato dal form dato che lo avevamo definito come valore della proprietà action.

Codice completo

Il codice completo dei tre file del nostro CAPTCHA è disponibile su GitHub. Sulla destra è presente un pulsante Clone or download con cui è possibile anche scaricare un file ZIP pronto per l’uso.

Tutte le lezioni

1 ... 44 45 46 ... 59

Se vuoi aggiornamenti su Realizzare un sistema CAPTCHA con PHP inserisci la tua e-mail nel box qui sotto:
Tags:
 
X
Se vuoi aggiornamenti su Realizzare un sistema CAPTCHA con PHP

inserisci la tua e-mail nel box qui sotto:

Ho letto e acconsento l'informativa sulla privacy

Acconsento al trattamento di cui al punto 3 dell'informativa sulla privacy