Czy widząc dużą liczbę komentarzy do twojego newsa czujesz podekscytowanie? Co z tego, gdy połowa z nich okazuje się być wytworem wrednych internautów – floodem. Zapomnij! W tym tutorialu opisze jak w prosty sposób zrealizować ochronę antyfloodową.
Skrypt ochrony antyfloodowej ma bardzo szerokie zastosowanie we wszelkiego rodzaju formularzach, które służą do wypowiadania się przez internautów na naszych stronach WWW. Ogólna idea takiego skryptu opiera się na ograniczeniu użytkownikowi możliwości dodania jednego posta po drugim w określonym interwale czasu. W tym tutorialu przedstawię 2 sposoby tworzenia takiego skryptu.
Wykorzystanie mktime()
Sposób pierwszy opierał się będzie na danych przekazanych w formularzu. Zostanie on zrealizowany w oparciu o dwa pliki. Oto kod źródłowy pierwszego z nich: form.php
| <? if (isset($_SERVER[’HTTP_X_FORWARDED_FOR’])) { $ip = $_SERVER[’HTTP_X_FORWARDED_FOR’]; } else { $ip = $_SERVER[„REMOTE_ADDR”]; } $date = mktime(); echo „<form method=post name=post action=add.php> nick: <br> <input type=text name=nick size=22><br> tekst: <br><textarea name=body maxlength=650 rows=8 cols=40> </textarea> <input type=hidden name=ip VALUE=$ip> <input type=hidden name=date_post VALUE=$date> <br> <INPUT TYPE=submit value=Dodaj > </form>”; ?> |
Jak widzimy przed wyświetleniem właściwego formularza pobieramy dwie przydatne nam informacje: IP użytkownika oraz datę w formacie UNIXowym – funkcja mktime(). To właśnie ta data jest głównym elementem realizacji naszego skryptu. Podstawową zaletą UNIXTIME, wykorzystaną przez nas, jest fakt, że posługuje się on samymi sekundami. To pozwala nam na swobodne liczenie różnicy czasu. Oto kod źródłowy drugiego pliku: add.php
| <?php $dane = file(’dane.dat’); $total = count($dane); $i = $total-1; $wiersz = explode(’||’, $dane[$i]); if ($wiersz[2] = $_POST[’ip’]) { $floodtime=$_POST[’date_post’] – $wiersz[3]; } if ($floodtime < ’30’) { echo 'Nie powtarzaj sie!’; } else { $file=fopen(’dane.dat’, 'a’); flock($file, '2′); fwrite($file, „$nick||$body||$ip||$date_post /n”); flock($file, '3′); fclose($file); echo 'Komentarz został dodany!’; } ?> |
Krok 1. – sprawdzenie IP
Krok 2. – porównanie czasów
Krok 3. – sprawdzenie wartości zmiennej $floodtime i podjęcie stosownej akcji
Krok 1. polega na sprawdzeniu IP ($wiersz[2]) z ostatnio dodanego postu. Jeśli to IP zgadza się z IP użytkownika wtedy przystępujemy do kroku 2. – obliczamy różnicę pomiędzy czasem wysłania ostatniego postu ($wiersz[3]) z czasem wysłania postu obecnego czyli zmienna $_POST[’date_post’] przekazana z pliku form.php do add.php za pomocą formularza. Następnie, jeśli ta różnica jest mniejsza od 30 (wartość interwału sekundowego może być dowolna), wykonujemy krok 3 – drukujemy komunikat o ochronie antyfloodowej, w przeciwnym wypadku dodajemy wpis do pliku. Przy okazji wpisania do pliku daty dodania postu warto wspomnieć, że jest ona bardzo często wyświetlana wraz z pozostałą zawartością formularza na naszej stronie. Z tego prostego względu, aby data była czytelna i przystępna dla każdego, trzeba wykonać następujące polecenie (przy założeniu, że podczas odczytu z pliku, za datę będzie odpowiadała zmienna $wiersz[3]):
|
$data = date („Y-m-d”, $wiersz[3]); |
Wtedy, jak widać, w zmiennej $data będzie zachowana data gotowa do wyświetlenia 🙂
Wykorzystanie cookies
Sposób drugi – wykorzystujący możliwości ciasteczek – jest znacznie efektywniejszy zarówno ze względu na swoją funkcjonalność jak i ilość wykonywanych poleceń. Realizujemy go również na bazie 2 plików. Oto kod źródłowy pierwszego z nich: form.php
| <?php echo „<form method=post name=post action=add.php> nick: <br> <input type=text name=nick size=22><br> tekst: <br><textarea name=body maxlength=650 rows=8 cols=40> </textarea> <br> <INPUT TYPE=submit value=Dodaj > </form>”; ?> |
Warto zauważyć, że w pliku tym nie ma pobierania IP czy też daty – zwyczajny formularz służący do przekazywania danych pomiędzy plikami. Kod źródłowy drugiego pliku wygląda następująco: add.php
| <?php ob_start(); if($antyflood != '1′) { setcookie(„antyflood”, „1”, time()+30); $file=fopen(’dane.dat’, 'a’); flock($file, '2′); fwrite($file, „$nick||$body /n”); flock($file, '3′); fclose($file); echo 'Komentarz został dodany!’; } else { echo 'Nie powtarzaj się!’; } ob_end_flush(); ?> |
Krok 1. – sprawdzenie czy ciasteczko jest ustawione
Krok 2. – podjęcie odpowiedniej akcji w zależności od kroku 1. Warto zauważyć, że w tym pliku, w przeciwieństwie do poprzedniej wersji, kod ogranicza się do kilku linijek. Nietrudno zauważyć, że w pierwszej kolejności skrypt sprawdza czy cookie o nazwie “antyflood” jest ustawione (krok 1.). Jeśli tak się NIE dzieje, skrypt ustawia cookie na 30 sekund i dodaje wpis do pliku – w przeciwnym razie drukuje komunikat o ochronie antyfloodowej (krok 2.). Chciałbym jeszcze zwrócić uwagę na pewną kwestię techniczną – jak widzicie na początku i na końcu skryptu umieściłem odpowiednio znaczniki ob_start(); i ob_end_flush(); – dzięki nim możliwe jest wysłanie ciasteczek ze środka strony.
Co prawda problem uwidacznia się tylko w części przypadków, nie mniej jednak umieszczenie tych znaczników profilaktycznie jest jak najbardziej wskazane. W ten oto prosty, acz funkcjonalny, sposób możemy obronić naszą witrynę przed nierozmyślnymi atakami “Scrypt Kiddies” czyli pseudohackerów. Niestety, z moich obserwacji wynika, że niewiele skryptów korzysta z antyfloodowego “ochroniarza” – a urządzenie, jak widać, ciekawe i przydatne.
