Guida [GUIDA]Come creare convalidazione Captcha per un form web

Stato
Discussione chiusa ad ulteriori risposte.

ErNabbone

Utente Gold
24 Settembre 2008
765
51
121
328
Ultima modifica da un moderatore:
[font='Georgia, Times New Roman, Times, serif']Introduzione

In questa guida cercherò di spiegarvi molto semplicemente come inserire una convalidazione captcha in un vostro form qualunque (captcha è l'acronimo di "Completely Automated Public Turing test to tell Computers and Humans Apart").


__________________

Requisiti software

Per il funzionamento di tale sistema, abbiamo bisogno di:
○ Un database MySql per il salvataggio di stringhe casuali e i rispettivi dati (data di creazione, di scadenza, etc.);
○ Nel nostro server "hostante" deve essere installato php 4.5 o superiore.

__________________

Spiegazione & svolgimento

Di seguito spiegherò i codici php e come inserirli in una nostra pagina php.
Come prima cosa dobbiamo creare una tabella di nome "validation" in un nostro database che contenga quattro colonne:
• "id" (Codice INT con auto incremento numerale);
• "url_key" (Codice generato casualmente dallo script);
• "captcha" (Stringa di numeri e lettere che comparira sulla nostra immagine);
• "expire_date" (Legge la data di creazione della form e la stampa).

Perr far ciò potete o usare il caro e vecchio navicat, o eseguire una query direttamente dal pannello sql (richiamabile dal dos con il comando mysql_ se disponiamo della versione 5.0 o superiore):
Codice:
CREATE TABLE validation (
   id INT UNSIGNED NOT NULL AUTO_INCREMENT,
   url_key CHAR(40) UNIQUE NOT NULL,
   captcha CHAR(32) NOT NULL,
   expire_date DATETIME NOT NULL,

   PRIMARY KEY(id),
   INDEX(url_key)
);

Dopodichè iniziamo con i codici veri e propi da inserire nella nostra pagina php.
Lo script che andremo a creare non utilizzerà cookie o sessioni dati per il salvataggio di informazioni per la convalidazione dei dati, ma creerà un form sql nella tabella da noi creata all'apertura della pagina web: la pagina in cui è salvato il form alla sua visualizzazione genererà una stringa casuale che verrà salvata nel database, al quale verrà associata una chiave casuale univoca.

Inseriamo quindi nella nostra pagina web (prima del tag <html> se possibile, oppure tra i tag <header> e </header>):
Codice:
<?php

$pdo = new PDO('mysql:host=IPDATABASE;dbname=NOMEDATABASE', 'NOMEACCOUNT', 'PASSWORD');

$stmt = $pdo->prepare("SELECT * FROM validation WHERE url_key = ? AND expire_date > NOW()");
$stmt->execute(array($_GET['token']));

$row = $stmt->fetch(PDO::FETCH_ASSOC);

$texture = imagecreatefrompng('texture.png');

$source = imagecolorat($texture, rand(0, imagesx($texture)), rand(0, imagesy($texture)));
$r = ($source >> 16 & 0xff) + 50;
$g = ($source >> 8 & 0xff) + 50;
$b = ($source & 0xff) + 50;
$text_color = imagecolorallocate($texture, $r, $g, $b);

imagestring($texture, 5, (imagesx($texture) - strlen($row['captcha']) * 5)/ 2, 5,  $row['captcha'], $text_color);

header('Content-Type: image/png');

imagepng($texture);

imagedestroy($texture);

?>

Notare in quest' ultimo codice la generazione casuale di alfanumerici Esadecimali. Concetto molto semplice e allo stesso tempo complesso da tradurre in codici.

Ora passiamo alla creazione del codice casuale e del form con richiesta di convalida.
Quindi sempre prima del tag <html>, inseriamo il codice:

Codice:
<?php

function random_string($len)
{
   $string = "";
   $chars = array("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
               "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
               "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G",
               "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
               "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2",
               "3", "4", "5", "6", "7", "8", "9");
   for($i = 0; $i < $len; ++$i)
   {
      shuffle($chars);
      $string .= $chars[0];
   }
   
   return $string;
}

$message = 'Per andare avanti, riscrivere il codice alfanumerico:';

$pdo = new PDO('mysql:host=IPDATABASE;dbname=NOMEDATABASE', 'IDACCOUNT', 'PASSWORD');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

if(isset($_POST['validate_token']))
{
   // Qui esegue la convalida
   $stmt = $pdo->prepare("SELECT * FROM validation WHERE url_key = ? AND expire_date > NOW()");
   $stmt->execute(array($_POST['token']));

   $row = $stmt->fetch(PDO::FETCH_ASSOC);
   
   $message = ($row && ($row['captcha'] == $_POST['validate_token'])) ? 'token esatto' : 'token <strong>NON</strong> esatto';
   $stmt = $pdo->prepare("DELETE FROM validation WHERE url_key = ?");
   $stmt->execute(array($_POST['token']));
}

// Elimino tutti i form dal database scaduti
$pdo->query("DELETE FROM validation WHERE expire_date <= NOW()");

// Genero casualmente un form per la tabella validation
$url_key = sha1(uniqid(rand(), true));
$captcha = random_string(6);
$stmt = $pdo->prepare("INSERT INTO validation (id, url_key, captcha, expire_date) VALUES ('', ?, ?, DATE_ADD(NOW(), INTERVAL 5 MINUTE))");
$stmt->execute(array($url_key, $captcha));

?>

Ora passiamo all'azione diretta sul form:
cerchiamo il tag <form*>;
lì dove ci fa più comodo, inseriamo il tag
Codice:
<?php echo $message; ?>
<input type="hidden" name="token" value="<?php echo $url_key; ?>" />
<img src="captcha.php?token=<?php echo $url_key; ?>" width="200" height="30" /><br/>
<input type="text" name="validate_token" />
<input type="submit" name="action" value="Test" />

!Attenzione!: Nei vostri form, al 90% dei casi è già esistente l'ultimo tag <input type="submit"*>, in tal caso non inserire due volte lo stesso "tag" bensì eliminare quello nell'ultimo Codice da me fornitovi.

__________________

Conclusione

Spero che questi script siano utili a qualcuno e spiegati in modo abbastanza chiaro e semplice.
Inoltre vi informo che per alcuni script ho preso spunto da internet (come tutti del resto) e che in ogni caso non sono del tutto sicuri: consiglio per questo quantomeno di cambiare i nomi delle stringhe.

Un saluto,
Erich alias ErNabbone.
[/font]
 
  • Mi piace
Reazioni: IlRosso™
Erich sei sempre il meglio *-* ... ti ricordi ancora di me ...no?

[font='Georgia, Times New Roman, Times, serif']Certo ;) .
lol, non hai idea dei casini che sto facendo con quel vecchio autopatcher!

Comunque mi ero quasi rassegnato al fatto che nessuno Postreplizzava in questo thread ;) .
[/font]
 
XD tranquillo ci pensa il buon vecchio Pavus xD
comunque fra poco finisco una nuova versione dell'autopacher moooolto più semplice della prima... se vuoi appena è pronta te la passo in anteprima ;)
 
Buona guida, però:
1. Non tutti potrebbero avere l'estensione PDO installata sulla loro versione di PHP (alcuni host usano versioni più vecchie della 5.1)
2. C'è qualcosa che non mi convince per quanto riguarda l'utilizzo del database al posto delle sessioni. Volendo, in quei 5 minuti che concedi per l'immissione del captcha, si potrebbe automatizzare il processo e quindi, con lo stesso token, inviare più di una volta il form desiderato.
3. Non capisco perchè fai tutto quel casino per generare un colore casuale XD Tiri in ballo i numeri esadecimali (che non c'entrano granchè 0.o), mentre avresti potuto usare un semplice mt_rand(0,255)

Ma in ogni caso, questa guida servirà a fornire un minimo di protezione per chi queste cose non le sapeva ;) Quindi bravo!
 
Ultima modifica:
XD tranquillo ci pensa il buon vecchio Pavus xD
comunque fra poco finisco una nuova versione dell'autopacher moooolto più semplice della prima... se vuoi appena è pronta te la passo in anteprima ;)

[font='Georgia, Times New Roman, Times, serif']Addirittura?
Grazie! Poi magari avrei due cosette da dirti su skype, qui non finiamo in OT.

[€dit]: Sono ben consapevole dei rischi che si corrono usando quei codici e l'ho scritto nel post principale.
Penso però che usando tutti quegli script già fatti strabuggati non diventi un problema aggiungere un piccolo bug, che può essere aggirato in quanto può connettere in un altro database creato apposta per tale scopo (per esempio uno di altervista :asd:).

Per quanto riguarda i colori, io amo l'esadecimale *-*
[/font]
 
  • Mi piace
Reazioni: mythicalfaber
[font='Georgia, Times New Roman, Times, serif']Sono ben consapevole dei rischi che si corrono usando quei codici e l'ho scritto nel post principale.
Penso però che usando tutti quegli script già fatti strabuggati non diventi un problema aggiungere un piccolo bug, che può essere aggirato in quanto può connettere in un altro database creato apposta per tale scopo (per esempio uno di altervista :asd:).[/font]
Anche connettendo a un altro database il problema c'è sempre, i 5 minuti di tempo li lasci e non elimini il token subito dopo l'utilizzo, quindi potrebbe venir usato quante volte si vuole in quei 5 minuti. Ma certo, non è un problema così grave...

[font='Georgia, Times New Roman, Times, serif']Per quanto riguarda i colori, io amo l'esadecimale *-*
[/font]
:asd:
 
Anche connettendo a un altro database il problema c'è sempre, i 5 minuti di tempo li lasci e non elimini il token subito dopo l'utilizzo, quindi potrebbe venir usato quante volte si vuole in quei 5 minuti. Ma certo, non è un problema così grave...


:asd:

[font='Georgia, Times New Roman, Times, serif']Beh, questo sicuramente, ma il tempo può essere diminuito ovviamente.

[/font]
 
  • Mi piace
Reazioni: Finallycri
Stato
Discussione chiusa ad ulteriori risposte.