PHP: skrypt CAPTCHA

Dawno nosiłem się napisaniem tej notki, a mianowicie chciałbym pokazać Wam jak napisać prosty system CAPTCHA, który możecie wykorzystać na swojej stronie internetowej. Zastosowanie tej funkcji pozwoli Ci na zabezpieczenie strony przed niechcianym spamem w różnorakich formularzach, komentarzach czy zakładaniem kont przez roboty. Skrypt składa się tak naprawdę z dwóch plików.

W pierwszym, który nazwę tokeny.txt, który zawierać będzie zbiór wyrazów, z którego jedno losowe słowo będzie wyświetlał nasz skrypt docelowy. Jest to zwykły plik tekstowy, gdzie każda nowa linijka to kolejne słowo. Przykładowa struktura tego pliku:

1
2
3
4
n1eb0
w1at4
dys7y
b4tut

Zapisujemy plik i wrzucamy na serwer do jakiegoś katalogu, np. includes. Ważne jest, aby plikowi nadać chmod 600, tak aby tylko skrypt miał do niego dostęp i nie można go będzie wyświetlać z poziomu przeglądarki.

Przejdźmy teraz do głównego pliku token.php, który będzie odpowiedzialny za generowanie odpowiedniego słowa przy formularzach na stronie. Skrypt do poprawnego działania wymaga obsługi biblioteki GD przez serwer. No to zaczynamy!

1
2
3
4
5
6
7
8
9
10
<?php

$words = file('includes/tokeny.txt');

if(isset($_GET['id']))
{
    $nr = $_GET['id'];
} else {
    $nr = rand(0, count($words) - 1);
}

Zaczynamy od załadowania wszystkich słów z pliku do tablicy. W przypadku podania zmiennej ‚id’ przy wywołaniu skryptu przypisujemy ją do zmiennej $nr, jeśli zmienna nie została podana zostaje wygenerowana losowo w dalszej części warunku.

1
2
3
4
$height = 100;
$width = 250;

$pic=ImageCreate($width, $height);

Następnie definiujemy wymiary obrazka jaki będzie generował skrypt i go tworzymy za pomocą metody ImageCreate()

1
2
3
4
5
6
7
8
9
10
11
12
13
$white = ImageColorAllocate($pic, 255, 255, 255);
$black = ImageColorAllocate($pic, 0, 0, 0);

$color_nr = 3;
for($i = 0; $i < $color_nr; $i++)
{
        $random_1 = rand(0, 255);
        $random_2 = rand(0, 255);
        $random_3 = rand(0, 255);
        $color[$i] = ImageColorAllocate($pic, $random_1, $random_2, $random_3);
}

ImageFill($pic,1,1,$white);

Dalej definiujemy biały i czarny kolor oraz pewną gamę losowo wygenerowanych kolorów, które przydadzą się w dalszej części skryptu. Dodatkowo stworzony w poprzednim kroku obraz wypełniamy białym tłem.

1
2
3
4
5
6
7
8
9
10
for($i = 0; $i < 200; $i++)
{
        $random_1 = rand(0, $width);
        $random_2 = rand(0, $height);
        $random_3 = rand(0, $width);
        $random_4 = rand(0, $height);
        $random_5 = rand(0, $color_nr);

        ImageLine($pic, $random_1, $random_2, $random_3, $random_4, $color[$random_5]);
}

Dzięki powyższym zapisom na naszym obrazku generujemy 200 losowych punktach, których kolory również zostały wylosowane w poprzednim kroku.

1
2
3
4
5
6
7
8
9
10
$word = $words[$nr];
$font = "arial";

for($i = 0; $i < count($words); $i++)
{
    $size = rand(2,5);
    $angle = rand(-45,45);

    imagettftext($pic, $size, $angle, $i*30+7, rand(4, 6), $black, $font, trim($word[$i]));
}

Następnie do zmiennej $word przypisujemy wybrane w pierwszym kroku słowo (za pomocą indeksu $nr odnosimy się do konkretnej wartości elementu tablicy $words) i wybieramy czcionkę w jakiem ma zostać „napisane” nasze słowo. W pętli wypisujemy losowe słowo litera po literze. Losowany jest rozmiar i kąt pod jakim wyświetlana będzie każda litera. Liter będą oddalone od lewej krawędzi o 7 pikseli i od siebie o 30 pikseli. Dodatkowo od górnej krawędzi będą oddalone od 4 do 6 pikseli (wartość będzie generowana losowo).

1
2
3
4
Header("Content-type: image/gif");
ImageGIF($pic);

?>

W ostatnim kroku wygenerowany obrazek wysyłamy do przeglądarki.

Jak wykorzystać w formularzu skrypt?

Poniżej znajduje się przykładowy kod formularza do dodawania komentarzy:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
echo '<center><form action="save_comment.php" method="post">'
        .'<table border="0" align="center" width="400">'
        .'<tr><td>Autor: * </td>';
            echo '<td><input type="text" name="author" value="'.$author.'" size="25">';
        echo '<tr><td>Komentarz: * <br></td>'
        .'<td><textarea name="comment" rows="10" cols="30">'.$comment.'</textarea>';
        echo '</td></tr>';
            $words=file('includes/tokeny.txt');
            $id=rand(0,count($words)-1);

            echo '<tr><td><img src="token.php?id='.$id.'"></td><td><input type="text" name="code" size="20">';
            echo '</td></tr>';
            echo '<input type="hidden" name="token" value="'.$id.'">';
 
        echo '<tr><td colspan="2"><b>Wymagane</b></td></tr>'
        .'</table>'
        .'<input type="hidden" name="nid" value="'.$nid.'">'
        .'<input type="hidden" name="op" value="save_comment">'
        .'<br><br><input type="submit" value="Dodaj komentarz"></center>'
        .'</form>';

Weryfikacja tokena odbywa się w pliku save_comment.php, który wygląda tak:

1
2
3
4
5
6
$words=file('includes/tokeny.txt');
        if((trim($words[$los])!=$code) {
            echo "<font style="color:red;font-weight:bold;font-size:12px">Zły kod!</font>";
        } else {
                       //dodanie komentarza do bazy
                }

W taki oto sposób możemy choć trochę zabezpieczyć się przed robotami, które atakują naszą stronę zasypując ją niepotrzebnym spamem.

Leave a Comment

three × 4 =