Prosta captcha obrazkowa w formularzu, przechowywana w sejsi

bordeux

Kiedyś chciałem zabezpieczyć formularz Księgi Gości przed robotami sieciowymi (też spamem).

Na początek stworzymy plik obrazek.php. Będzie on tworzył obrazek. Uzupełnij go kodem:

<?php
/**************************************************************************
****************   Token By Bordeux.NET            **************************
****************   File name :   Obrazek.php           *********************************
****************   Start   :   28.05.2007 r.        **********************************
***************************************************************************/
session_start();
$slowo= $_SESSION['haslo'];// dane z sesji
$wysokosc=20;
$szerokosc=60;


$pic=ImageCreate($szerokosc,$wysokosc);
$bialy=ImageColorAllocate($pic,255,255,255);
$czarny=ImageColorAllocate($pic,0,0,0);
$szary=ImageColorAllocate($pic,150,150,150);

ImageFill($pic,1,1,$bialy);
for($i=0;$i<200;$i++)
    {
    $los1=rand(0,$szerokosc);
    $los2=rand(0,$wysokosc);
    
    ImageLine($pic,$los1,$los2,$los1,$los2,$szary);
    }
    for($i=0;$i<strlen($slowo) ;$i++)
    {
    $rozmiar=rand(2,5);

    ImageString($pic,$rozmiar,$i*10+7,3,trim($slowo[$i]),$czarny);
    }
    Header("Content-type: image/gif");
ImageGIF($pic);

?>

Tutaj pobieramy dane z sesji. W tym przypadku wylosowanego hasła. Teraz czas na formularz a zarazem na funkcje losująca hasło. Wiec tworzymy plik formularz.php i uzupełniamy go kodem

<?php
/**************************************************************************
****************   Token By Bordeux.NET            **************************
****************   File name :   formularz.php           *********************************
****************   Start   :   28.05.2007 r.        **********************************
***************************************************************************/
session_start(); //otwieramy sesje
function generujHaslo()
{
  $dlugosc_hasla = 5;
  $zestaw_znakow = "abcdefghijklmnopqrstuvwxyz0123456789";
  srand((double)microtime() * 1000000);

  while(strlen($haslo) < $dlugosc_hasla)
  {
    $znak = $zestaw_znakow[rand(0, strlen($zestaw_znakow) - 1)];
    if(!is_integer(strpos($haslo, $znak))) $haslo .= $znak;
  }
  return $haslo;
}
$Haslo= generujHaslo();
$_SESSION['haslo'] = $Haslo; // dane do sesji
?>
<form action='zapisz.php' method='post'><input type='text' name='text' maxlength='100'>
<? echo '<img src="obrazek.php">: Haslo z Obrazka<input type="text" name="token" size="5">'; ?> <input type='submit' value='O.K'></form>

Tutaj otwieramy sesje i wpisujemy do niej pod zmienna haslo wylosowane hasło. Funkcje losującą zlazłem tutaj, na http://4programmers.net/PHP/FAQ/Jak_wygenerowa%C4%87_losowe_has%C5%82o_z_nie_powtarzaj%C4%85cymi_si%C4%99_znakami
. Teraz pora na kod który sprawdza czy hasło jest poprawne. Wiec tworzymy plik zapisz.php i uzupełniamy go kodem:

<?php
/**************************************************************************
****************   Token By Bordeux.NET            **************************
****************   File name :   Zapisz.php           *********************************
****************   Start   :   28.05.2007 r.        **********************************
***************************************************************************/

if ($_POST['token'] == $_SESSION['haslo']) {
    echo "Token poprawny";
    //dalsze jakieś czynności
} else {
    echo "Token nie poprawny";
    //dalsze jakieś czynności
}

Teraz roboty tak łatwo nie wpiszą się do naszej księgi lub coś w tym stylu.

16 komentarzy

Ktos : user image O boto i ułomo odporny :)

Wydaje mi się że umieściłem coś takiego w downloadzie wcześniej.
Napewno. Oczywiście jak coś nie pasuje to można zmienić kod.
Innym sposobem jest filtrowanie tekstu. Wyszukiwanie wyrazów takich jak viagra itp.

Waszmość nie zrozumiał - chodziło mi o czas edycji a nie ilość znaków. Standardowo, ze względu na masowość, automaty wprowadzają wpisy bardzo szybko. Na pewno krócej niż 2-3 sekundy. A to jest czas jaki minimalnie musi poświęcić człowiek wpisaniu choćby smiley'a i poklikaniu na przyciski. Jeśli wytniesz wpisy szybkie, załatwiasz 99% automatów i flooderów. Nie deprecjonuję zgrabności Twego skryptu obrazkowego, szukam po prostu bardziej finezyjnych metod niż te stosowane w większości przypadków. Poza tym, wspomniałem, że obrazki nie są specjalnie przyjazne, szczególnie jeśli skrypt rozpoznaje wielkość znaków a małe "o" i duże "O" wyglądają podobnie.

Pozdrawiam
WS

Tak, to coś nazywa się "CAPTCHA".
A ja dzisiaj widziałem genialną metodę - trzeba było policzyć granicę funkcji podanej w obrazku. To było podobne do mojego pomysłu: "rozwiąż całkę z obrazka" ;-)

lepiej "CAPTCHA", jako przyjęta powszechnie nazwa niż "token"

Waszmość Pana blokowałem. Do 1024 znaków.

A po długości edycji waść blokował?

Tez blokowałem, trochę mi sie ip nazbierało... http://www.bordeux.yoyo.pl/gsx/Ksiega/ban.txt :)

W takim przypadku jak podajesz - rzeczywiście rysunki mogą mieć sens. Nie miałem nigdy takiego - jakbym miał to zacząłbym od blokowania user-agenta (jeśli niestandardowo by się przedstawiał), IP lub zakresu IP intruza, czasu edycji (np. edycja poniżej 2 sekund - wywalaj). Nie lubię obrazków bo są not user-friendly.
Pozdrawiam
WS

A tego nie zrobiłem

Tak, ale np. ktoś może ci zapchać tez księgę. Np. Napisze program, który jak najęty wysyła ci jakieś bezsensowne wpisy w postaci post. Miałem taki przypadek

To proste. Mniej pisania. Jakieś 5 linijek, a efekt bardzo skuteczny. Po co zatem bawić się w obrazki tam, gdzie prostsza metoda działa dobrze?

Pozdrawiam
WS

No mozna i tak, ale po co sie bawic w filtry

By zabezpieczyć Księgę Gości po prostu pozakładałem filtry na wpisy. Okazało się bowiem, że 90% wpisów zawiera ciąg "Thank you". Inne zawierają linki, których nie dopuszczam w księdze gości. Jest jeszcze filtr po słowach "cialis", "viagra", itp.
Działa to w 99%. Resztę (raz na miesiąc jeden wpis) wycinam ręcznie.
Aha, stronka jest mojej córeczki - niemodyfikowana od 3 lat, więc kod beznadziejny, ale jak kto chce niech zagląda: www.gretka.vel.pl
Pozdrawiam
WS

Ale obrazek tworzysz masakryczny. Nieczytelny dla człowieka, za to prosty dla maszyn.

Tak, może, ale inny kod. Może podobny.. A z tym filtrowaniem to jest o tym cały czas mowa. Wiec można powiedzieć ,,Wczas"