Programowanie
- Java [ 0 ]
- C [ 0 ]
- PHP [ 1 ]
- Modelowanie [ 0 ]
Layout
- CSS [ 0 ]
- xHTML [ 0 ]
- Photoshop [ 0 ]
Artykuły
- Artykuły [ 0 ]
[TEST!!]Sposób na walkę ze spamem w formularzach POST
Obrona przed spamem w formularzach kontaktowych.
Dzisiaj chciałem opisać kilka metod dotyczących obrony przed wysyłanym spamem przez roboty. Jedna z najczęściej stosowanych metod to używanie tokenów, czyli obrazków z napisem, które przepisuje osoba wysyłająca wiadomość. Minusem tej metody jest to że wymaga się od użytkownika każdorazowo wpisywania dodatkowych znaczków, a jak ktoś źle zaprojektuje formularz to po błędnym przepisaniu trzeba ponownie wprowadzać dane. Nie zmienia to faktu, że jest to obecnie jedna z lepszych(najczęściej używanych) metod i jeżeli wszystko jest z głową zaprojektowane i nie dopuszczamy do sytuacji opisanej wcześniej możemy śmiało korzystać z tej metody.
Jeżeli chodzi o tokeny to znajdziemy bardzo dużo tutoriali czy gotowych bibliotek do użycia, dlatego opiszę inne metody obrony przed spamem. Metody tak naprawdę działają na bardzo podobnej zasadzie jednak korzystają z różnych elementów php dlatego dla początkujących programistów ten artykuł może okazać się pomocny.
Opiszę zatem metody wykorzystujące poniższe opcje:
- - Cookies
- - Sesje
- - Pliki
Uwagi:
- 1. Kod przykładów podam w 'czystym' php jak i dla frameworka Code Igniter (jest to dość stary framework - jednak działa jeszcze na serwerach z php4), użycie w Kohanie czy Zend Framework nie powinno się wiele różnić.
- 2. Metody nie nadają się raczej do wykorzystania w formularz komentarzy - bardzo często można zobaczyć zażartą dyskusje między komentującymi(dobrym przykładem jest portal wykop.pl), daje możliwość komentowania co godzinę raczej ograniczamy użytkowników.
Cookies
Cookies czyli tzw. ciasteczka tworzone są po stronie klienta. Tworząc ciasteczka możemy ustawić czas ich życia - ustawiając czas życia na 1 godzinę, a następnie na stronie sprawdzamy istnienie naszego ciastka - jeśli jest tzn. że osoba wysłała już wiadomość i musi poczekać. W ciasteczku możemy przechować takie dane jak czas wysłania - dzięki temu możemy poinformować użytkownika za ile będzie mógł wysłać kolejną wiadomość.
Minusami tej metody jest to że użytkownik może ręcznie skasować stworzony przez nas cookies i wysyłać dalej wiadomości.
Troszkę kodu:
Tworzenie ciasteczka - należy użyć w momencie wysłania formularza (po jego obsłużeniu).
// ładowanie pomocnika obsługującego ciastka $this->load->helper('cookie'); // Używamy tabeli jakbyśmy chcieli coś jeszcze dołożyć // tworzenie tabeli cookie która jest wykorzystana do ustawiania cookies // serialize() jest konieczne ponieważ podajemy tablicę, // która jest zamieniana na jeden łańcuch 'name' => 'email_confirm', 'domain' => '.wlodi.net', 'path' => '/', 'prefix' => 'wlodinet_', ); // ustawienie ciasteczka set_cookie($cookie);
Sprawdzenie czy istnieje ciasteczko i odpowiednie działanie, należy wstawić przed obsłużeniem formularza. Pamiętamy, że korzystaliśmy z serialize() i aby odtworzyć dane musimy wykorzystać funkcje unserialize().
// do wyboru jeden z if-ów // zawiera filtr XSS if ($user_data_sended = get_cookie('email_confirm', TRUE)) // bez filtra XSS if ($user_data_sended = get_cookie('email_confirm')) { // obliczenie czasu pozostałego w sekundach // do sformatowania czasu można posłużyć się funkcją date() // nie będę już pisał tej części pozostawie // jako ćwiczenie dla czytelników } else { //użytkownik nie posiada ciastka - nie wysyłał jeszcze wiadomości // w tym miejscu można wrzucić obsługę wysłanej wiadomości }
Część bez frameworka - jest analogiczna, cały kod w jednym bloku podzielony komentarzami /**/ na dwie części
/* --- Ustawienie ciasteczka --- */ // Używamy tabeli jakbyśmy chcieli coś jeszcze dołożyć // Ustawiamy cookies '.wlodi.net', '/'); /* --- Sprawdzenie czy istnieje ciasteczko --- */ { // obliczenie czasu pozostalego w sekundach // do sformatowania czasu mozna posluzyc się funkcją date() // nie bede już pisał części fronend'u // jak pisalem wczesniej mozna wypisac za ile czasu // uzytkownik będzie mógł wysłać wiadomość } else { //uzytkownik nie posiada ciastka - nie wysylal jeszcze wiadomosci // w tym miejcu mozna wrzucic obsluge wyslanej wiadomosci }
Sesje
Kolejną metodą będzie użycie sesji - działanie i kod jest bardzo zbliżony. Tworzymi sesję oraz czas jej wygaśnięcia - usatwiając czas na 1 godzinę, a następnie na stronie sprawdzamy istnienie aktywnej sesji - jeśli jest tzn. że osoba wysłała już wiadomość i musi poczekać. W sesji i jak to było w ciasteczku przechowujemy takie dane jak czas wysłania - dzięki temu możemy poinformować użytkownika za ile będzie mógł wysłać kolejną wiadomość.
Minusami tej metody jest to że użytkownik może ręcznie skasować aktywną sesję.
Uwaga:
- 1. W Code Igniter w pliku application/config/config.php możemy ustawic żywotnosc sesi - jednak bedzie sie on odnosił do wszystkich sesji, nie jest to raczej pozadane - nawet jesli nie uzywamy na razie innej sesj w przyszlosci jesli bedziemy chcieli cos zmienic powstanie problem - i trzeba bedzie zmienic kodzik w wielu miejsca - dlatego nalezy zadbac o to odrazu, przechowujemy czas przesłania wiadomości, więc skorzystajmy z niego.
/* Tworzenie sesji */ // biblioteka obsługująca sesje $this->load->library('session'); // analogicznie jak w Cookies przechowujemy czas //na koniec ustawienie sesji $this->session->set_userdata($user_sended_data); /* Obsługa formularza */ $sended_time = $this->session->userdata('time'); if($sended_time + 3600 < $time()) { // uzytkownik poczekal godzinke mozemy dac mu wyslac e-mail } else { // uzytkownik nie poczekal wystarczajaco dlugo // podobnie jak w cookies blokujemy wysylanie po stronie frontendu }
Część bez frameworka, cały kod w jednym bloku podzielony komentarzami /**/ na dwie części
/* tworzenie sesji - powinno wystąpić na samym początku kodu */ // sprawdzenie i ustawienie czasu wyslania { } else { $sended_time = $_SESSION['time']; } { // uzytkownik poczekal godzinke mozemy dac mu wyslac e-mail } else { // uzytkownik nie poczekal wystarczajaco dlugo // podobnie jak w cookies blokujemy wysylanie po stronie frontendu }
Pliki
Ostanią metodą jaką opiszę jest wykorzystanie plików i tworzenie "bazy" adresów IP i adresów e-mail. Kilka słów o samej koncepcji:
Do przechowywania danych użyjemy pliku z zachowaniem formatu csv. Przykład zawartości takiego pliku
ip;czas_wyslania;email;ilosc_wiadomosci 127.0.0.1;12323423;mail@wlodi.net;2
Pierwszy wiersz jest opisem, ale rowniez w wypadku CI musi zostac - poniewaz wykorzystamy biblioteke ktora parsuje i obsluzy za nas plik csv i wymaga takiego formatu.
Dużym minusem tej metody jest to że większość surferów posiada zmienne IP i teraz ktos kto naprawde by chcial pospamowac, skrzynie odnawia polaczenie(jest to naszczecie dosc czasochlonne - nawet jak robil by to z automatu mozna zalozyc ze czas polaczenie to okolo 5s-10s) Jednak trzeba założyć, że wiele osób korzysta z sieci zatem blokada całego IP też nie jest najlepszym rozwiązaniem - chodź dość często stosowana przez serwisy WWW.
Jak widac z przechowywaniem danych w pliku wiaze sie wiele problemow, jednak oprócz tych minusow, takie przechowanie(dotyczy rowniez bazy danych) daje nam ogromne mozliwosci jesli chodzi o ich analize danych(adresy ip, e-mail)
Minusem dosc waznym w przypadku uzywania plikow do przechowywania danych jest ich przeglad jak posiadamy strone ktora jest przegladana przez wiele osob i dostajemy wiele wiadomosci to plik nam sie powieksza i jego przeszukiwanie moze trwac zbyt dlugo, dlatego powinnismy sie pokusic o tworzenie jednego duzego pliku - z wczesniej opisana baza adresów ip, email oraz jeden ktory jest czyszczony np. raz dziennie.
Jak wcześniej wspomniałem do parsowania pliku CSV posłużmy się biblioteką napisaną dla Code Igniter (jednak w przykładzie bez CI) też jej użyjemy ponieważ jest zgrabnie napisana i posiada jedynie te elementy których potrzebujemy. Autorem jest Pierre-Jean Turpeau strona biblioteki na CI http://www.codeigniter.com/wiki/CSVReader oraz trochę szerszy opis i przykłądy użycia http://blog.insicdesigns.com/2009/03/reading-csv-file-in-codeigniter/
Instalacja biblioteki w CI jest bardzo prosta wystarczy przekopiowac zawartość do folderu library w naszym projekcie.
Uwaga:
- 1. Ze względu na dość rozrastający się pierwszy artykuł opuszcze tutaj zapis do pliku danych, założe że plik już istnieje i mogę z niego korzystać
$this->load->library('csvreader'); $ip = $this->input->ip_address(); $filePath = 'file.csv'; // sparsowanie pliku i przekazanie danych do $data; $data = $this->csvreader->parse_file($filePath); // uzytkownik moze wysylac wiadomosc $check_ability = true; foreach($data as $field){ if($field['ip'] == $ip && $field['email']) // jesli mamy w bazie juz taki mail lub adres IP // sprawdzamy czas i okreslamy dostęp { $check_ability = false } } if($check_ability) { // mozemy obsluzyc wyslana wiadomosc // dodajemy dane(adres IP, e-mail) do pliku } else { // możemy obsluzyc kolege podając mu za ile bedzie mogl wyslac e-mail }
W pliku na początku podałem takie dane jak ilość_wiadomości - w tym przykładzie z tego nie korzystam, ale można założyć że dopiero po dwóch wiadomościach blokujemy dalsze wysyłanie, należy zatem skorzystać z $field['ilosc_wiadomosci'] w odpowiednim warunku(linia 45). Zostawiam to jako zadanie dla czytelników.
Wersja bez CI nie bedzie sie wiele roznic - biblioteka chodz w wersji dla CI moze byc wykorzystana w dowolnym miejscu. Poniewaz klaska jest bardzo zgrabnie napisana i bezsensu byloby pisac cos takiego na nowo, lepiej uzyc cos co juz jest i dziala sprawnie. Zatem do dziela - podobnie jw. trzeba sciagnac biblioteczke(jedna klasa). Plik bedzie mial identyczna postac:
ip;czas_wyslania;email;ilosc_wiadomosci 127.0.0.1;12323423;mail@wlodi.net;2 192.168.0.1;23324423;mail@wlodi.net;2
required_once('CSVReader.php'); $parser = new CSVReader(); $data = $parser->parse_file($file_path); // a reszta identyczna jw, jednak dla porządku skopiuje kod $check_ability = true; foreach($data as $field){ if($field['ip'] == $ip && $field['email']) // jesli mamy w bazie juz taki mail lub adres IP // sprawdzamy czas i okreslamy dostęp { $check_ability = false } } if($check_ability) { // mozemy obsluzyc wyslana wiadomosc // dodajemy dane(adres IP, e-mail) do pliku } else { // obslugujemy podając za ile bedzie mozna wyslac e-mail }
Na zakończenie dodam że w ostatniej metodzie można stosować bazę danych - rezygnujemy wtedy z CSV Readera i dane dotyczące użytkowników zapisujemy i odczytujemy z bazy. Jeśli ktokolwiek to przeczyta i nie będzie wiedział jak to zrobić może śmiało pisać, powiększe artykuł o tą metodę.
Chciałbym jeszcze dodac że jest to mój pierwszy artykuł dlatego proszę słowa krytymi(te motywujące) dotyczące artykułu.
W najbliższym artykule będę chciał pokazać swoją koncepcję wykorzystania biblioteki GD oraz tworzenie tekstów(przykład e-mai, gg na stronie) oraz tworzenie wykresów.
wlodi [ 2009-09-28 16:09:47 ]
