Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [Klasa] Antibot - przyjazna ochrona przed botami, Zamiennik dla captcha. Moduł przeznaczony dla Kohana.
phpion
post 14.05.2009, 21:34:35
Post #1





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Witam,
dziś napisałem prosty mechanizm ochrony przed spamującymi botami.

Demo modułu można zobaczyć tutaj:
http://kohana.phpworkstation.com/antibottest

Paczuszkę z niezbędnymi plikami oraz przykładem wykorzystania można pobrać stąd:
http://kohana.phpworkstation.com/download/antibot.zip

Oto pliki wchodzące w skład modułu:

modules/antibot/config/antibot.php
  1. <?php
  2. $config = array(
  3.    /**
  4.      * Tajny klucz służący do zakodowania nazw plików graficznych.
  5.      */
  6.    'security_key' => 'mójmegatajnyklucz',
  7.  
  8.    /**
  9.      * Nazwa katalogu / ścieżka katalogu z plikami graficznymi.
  10.      */
  11.    'images_directory' => 'img/antibot',
  12.    'randoms' => array(
  13.        /**
  14.          * Liczba losowanych poprawnych elementów.
  15.          */
  16.        'good' => 2,
  17.  
  18.        /**
  19.          * Liczba losowanych niepoprawnych elementów.
  20.          */
  21.        'bad' => 3
  22.    ),
  23.    'images' => array(
  24.        /**
  25.          * Tablica nazw poprawnych plików graficznych.
  26.          */
  27.        'good' => array(
  28.            '1.jpg',
  29.            '2.jpg',
  30.            '3.jpg',
  31.            '4.jpg',
  32.            '5.jpg'
  33.        ),
  34.  
  35.        /**
  36.          * Tablica nazw niepoprawnych plików graficznych.
  37.          */
  38.        'bad' => array(
  39.            '10.jpg',
  40.            '20.jpg',
  41.            '30.jpg',
  42.            '40.jpg',
  43.            '50.jpg'
  44.        ),
  45.    )
  46. );
  47. ?>


modules/antibot/libraries/Antibot.php
  1. <?php
  2. /**
  3.  * Klasa tworząca przyjazne zabezpieczenie formularzy przed atakami botów.
  4.  *
  5.  * Działanie klasy polega na wyświetleniu określonej liczby plików graficznych,
  6.  * wśród których znajduje się pewna liczba elementów, które należy zaznaczyć w formularzu.
  7.  *
  8.  * @author phpion
  9.  */
  10. class Antibot {
  11.    /**
  12.      * Losowy ciąg znaków wykorzystywany przy kodowaniu nazwy pliku graficznego.
  13.      *
  14.      * @var string
  15.      */
  16.    private $token = '';
  17.  
  18.    /**
  19.      * Tajny klucz bezpieczeństwa wykorzystywany przy kodowaniu nazwy pliku graficznego.
  20.      *
  21.      * @var string
  22.      */
  23.    private $security_key = '';
  24.  
  25.    /**
  26.      * Nazwa katalogu / ścieżka katalogu, w którym znajdują się pliki graficzne.
  27.      *
  28.      * @var string
  29.      */
  30.    private $images_directory = '';
  31.  
  32.    /**
  33.      * Tablica zawierająca informację o ilości losowanych plików graficznych z rozróżnieniem na typ (dobry/zły).
  34.      *
  35.      * $array = array(
  36.      *        'good' => 2,
  37.      *        'bad'  => 3
  38.      * );
  39.      *
  40.      * @var array
  41.      */
  42.    private $randoms = array();
  43.  
  44.    /**
  45.      * Tablica nazw plików graficznych służących do wyświetlania dobrych/złych elementów.
  46.      *
  47.      * $array = array(
  48.      *        'good' => array(1, 2, 3),
  49.      *        'bad'  => array(10, 20, 30
  50.      * );
  51.      *
  52.      * @var <type> tablica
  53.      */
  54.    private $images = array();
  55.  
  56.    /**
  57.      * Konstruktor klasy Antibot.
  58.      *
  59.      * Automatycznie pobiera potrzebne dane z pliku konfiguracyjnego.
  60.      */
  61.    public function __construct() {
  62.        $config = Kohana::config('antibot');
  63.  
  64.        $this->security_key = (string)$config['security_key'];
  65.        $this->images_directory = (string)$config['images_directory'];
  66.        $this->randoms = (array)$config['randoms'];
  67.        $this->images = (array)$config['images'];
  68.  
  69.        $this->set_token();
  70.    }
  71.  
  72.    /**
  73.      * Losuje listę plików graficznych.
  74.      *
  75.      * @return array Tablica zakodowanych nazw plików graficznych.
  76.      */
  77.    public function get_images() {
  78.        $return = array();
  79.  
  80.        foreach (array(self::GOOD, self::BAD) as $type) {
  81.            shuffle($this->images[$type]);
  82.            $images = array_chunk($this->images[$type], (int)$this->randoms[$type]);
  83.  
  84.            $return = array_merge($return, $images[0]);
  85.        }
  86.  
  87.        shuffle($return);
  88.  
  89.        foreach ($return as $key => $item) {
  90.            $return[$key] = $this->encode_image($item);
  91.        }
  92.  
  93.        return $return;
  94.    }
  95.  
  96.    /**
  97.      * Koduje nazwę pliku graficznego.
  98.      *
  99.      * @param string $image Nazwa pliku graficznego.
  100.      * @return array Zakodowana nazwa pliku graficznego.
  101.      */
  102.    private function encode_image($image) {
  103.        $input = Input::instance();
  104.  
  105.        return md5($this->encode_token().$image.$input->ip_address().$this->security_key);
  106.    }
  107.  
  108.    /**
  109.      * Wyszukuje prawdziwą nazwę pliku graficznego na podstawie jego zakodowanej nazwy.
  110.      *
  111.      * @param string Zakodowana nazwa pliku graficznego.
  112.      * @return string|boolean Prawdziwa nazwa pliku graficznego jeśli zostanie znaleziony; w przeciwnym razie zwraca FALSE.
  113.      */
  114.    private function find_image($encoded_image) {
  115.        $images = array_merge($this->images[self::GOOD], $this->images[self::BAD]);
  116.  
  117.        foreach ($images as $image) {
  118.            if ($this->encode_image($image) === $encoded_image) {
  119.                return $image;
  120.            }
  121.        }
  122.  
  123.        return FALSE;
  124.    }
  125.  
  126.    /**
  127.      * Zwraca obiekt typu Image reprezentujący plik graficzny.
  128.      *
  129.      * @param string Zakodowana nazwa pliku graficznego.
  130.      * @return Image|boolean Obiekt typu Image jeśli znaleziono prawdziwy plik graficzny; w przeciwnym razie zwraca FALSE.
  131.      */
  132.    public function get_image($encoded_image) {
  133.        $decoded_image = $this->find_image($encoded_image);
  134.  
  135.        return $decoded_image ? new Image($_SERVER['DOCUMENT_ROOT'].Kohana::config('config.site_domain').$this->images_directory.'/'.$decoded_image) : FALSE;
  136.    }
  137.  
  138.    /**
  139.      * Koduje token.
  140.      *
  141.      * @return string Zakodowany token.
  142.      */
  143.    private function encode_token() {
  144.        $return = $this->token;
  145.        $return = strrev($return);
  146.        $return = md5($return);
  147.        $return = substr($return, 9, 14);
  148.        $return = md5($return);
  149.  
  150.        return $return;
  151.    }
  152.  
  153.    /**
  154.      * Sprawdza czy użytkownik wskazał poprawne elementy z przedstawionej mu listy.
  155.      *
  156.      * @param array $checked Tablica zaznaczonych elementów.
  157.      * @return boolean TRUE jeśli zaznaczono poprawne elementy; w przeciwnym razie zwraca FALSE.
  158.      */
  159.    public function validate(array $checked = array()) {
  160.        $checked = array_unique($checked);
  161.  
  162.        if (count($checked) === (int)$this->randoms[self::GOOD]) {
  163.            $correct = 0;
  164.  
  165.            foreach ($this->images[self::GOOD] as $item) {
  166.                if (in_array($this->encode_image($item), $checked)) {
  167.                    $correct++;
  168.                }
  169.            }
  170.  
  171.            return $correct === (int)$this->randoms[self::GOOD];
  172.        }
  173.  
  174.        return FALSE;
  175.    }
  176.  
  177.    /**
  178.      * Ustawia token dla instancji klasy.
  179.      *
  180.      * Jeżeli nie przekazano parametru $token wówczas nadawany jest losowy token.
  181.      *
  182.      * @param string|NULL $token Token.
  183.      */
  184.    public function set_token($token = NULL) {
  185.        if (is_null($token)) {
  186.            $token = md5(uniqid());
  187.        }
  188.  
  189.        $this->token = (string)$token;
  190.    }
  191.  
  192.    /**
  193.      * Zwraca token.
  194.      *
  195.      * @return string Token.
  196.      */
  197.    public function get_token() {
  198.        return $this->token;
  199.    }
  200.  
  201.    /**
  202.      * Nazwa klucza dla poprawnych elementów.
  203.      */
  204.    const GOOD = 'good';
  205.  
  206.    /**
  207.      * Nazwa klucza dla niepoprawnych elementów.
  208.      */
  209.    const BAD = 'bad';
  210. }
  211. ?>


modules/antibot/controllers/antibot.php
  1. <?php
  2. /**
  3.  * Kontroler odpowiedzialny za wyświetlanie odpowiedniego pliku graficznego.
  4.  */
  5. final class Antibot_Controller extends Controller {
  6.    /**
  7.      * Zwraca do przeglądarki konkretny plik graficzny.
  8.      */
  9.    public function render_image() {
  10.        $image = (string)$this->input->get('image', '');
  11.        $token = (string)$this->input->get('token', '');
  12.  
  13.        $ab = new Antibot();
  14.        $ab->set_token($token);
  15.  
  16.        $image = $ab->get_image($image);
  17.  
  18.        if ($image instanceof Image) {
  19.            echo $image->render();
  20.        }
  21.    }
  22. }
  23. ?>

Jeżeli macie jakiekolwiek uwagi czy sugestie to chętnie się z nimi zapoznam smile.gif

Pozdrawiam,
pion
Go to the top of the page
+Quote Post
wookieb
post 14.05.2009, 21:39:44
Post #2





Grupa: Moderatorzy
Postów: 8 989
Pomógł: 1550
Dołączył: 8.08.2008
Skąd: Słupsk/Gdańsk




A czy dobrze napisany graficzny token nie bedzie lepszy?
System wybierania obrazków jest troche duzy a mniejsze wersja moze byc nieuzyteczna (Chodzi mi o zajetosc na stronie)
Uwazam ze najlepszym systemem antybotowym jest odpowiadanie na proste pytania. Np jest tak w wyszukiwarce na flashzone.pl
Pytanie typu: Jakiego koloru jest śnieg.
Przy odpowiednio częstym zmienianiu pytań, żaden bot tego nie łyknie.


--------------------
Go to the top of the page
+Quote Post
Riklaunim
post 14.05.2009, 21:45:14
Post #3





Grupa: Zarejestrowani
Postów: 640
Pomógł: 44
Dołączył: 8.02.2004

Ostrzeżenie: (0%)
-----


Ja tam stosuję tekstowe zabezpieczenie - podanie n-tej cyfry z podanej liczby. Automatyczne boty się na tym wysypują winksmiley.jpg


--------------------
Biblioteki: Skrypty, CMS | Kurs PHP | Python
Go to the top of the page
+Quote Post
pyro
post 14.05.2009, 21:50:02
Post #4





Grupa: Zarejestrowani
Postów: 2 148
Pomógł: 230
Dołączył: 26.03.2008

Ostrzeżenie: (0%)
-----


Cytat(Riklaunim @ 14.05.2009, 22:45:14 ) *
Ja tam stosuję tekstowe zabezpieczenie - podanie n-tej cyfry z podanej liczby. Automatyczne boty się na tym wysypują winksmiley.jpg


no zalezy jak to przedstawiasz uzytkownikowi... ja tam korzystam z captchy (klasa od google) i zabezpieczenie 100% skuteczne. @phpion, mi niestety pomysł nie wydaje się zbytnio użyteczny z powodów, które podał @wookieb. To troche proba wymyslenia czegos, co jest niepotrzebne winksmiley.jpg


--------------------
ET LINGUA EIUS LOQUETUR IUDICIUM
Go to the top of the page
+Quote Post
Crozin
post 14.05.2009, 23:08:03
Post #5





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Poza tym, nadal istnieje spora szansa na to, że bot złamie to - na zasadzie zaznaczania losowych checkboxów.
Go to the top of the page
+Quote Post
phpion
post 15.05.2009, 05:03:36
Post #6





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Cytat(wookieb @ 14.05.2009, 22:39:44 ) *
A czy dobrze napisany graficzny token nie bedzie lepszy?

Jak dla mnie captcha nie jest cudem wygody dla użytkownika końcowego stąd pomysł (w sumie gdzieś to już widziałem) o innym podejściu do zabezpieczenia.

Cytat(pyro @ 14.05.2009, 22:50:02 ) *
ja tam korzystam z captchy (klasa od google) i zabezpieczenie 100% skuteczne

j.w.

Cytat(Crozin @ 15.05.2009, 00:08:03 ) *
Poza tym, nadal istnieje spora szansa na to, że bot złamie to - na zasadzie zaznaczania losowych checkboxów.

Przy większej liczbie prawidłowych obrazków (np. 5 dobrych + 5 złych) szanse te są mniejsze. Poza tym wystarczy co jakiś czas zmienić ten stosunek i już smile.gif

Tak czy siak dzięki za opinie.
Go to the top of the page
+Quote Post
Crozin
post 15.05.2009, 05:21:21
Post #7





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Cytat
Przy większej liczbie prawidłowych obrazków (np. 5 dobrych + 5 złych) szanse te są mniejsze. Poza tym wystarczy co jakiś czas zmienić ten stosunek i już
Jest 6:20 i musze lecieć na autobus więc liczyć nie będę, ale wystarczy, że jedna na 100 prób "na ślepo" się powiedzie i już trzeba się liczyć z dziesiątkami botów dziennie, które przejdą walidację.

A czytanie instrukcji + rozpoznawanie (nie)prawidłowych obrazków przez użytkownika wydaje mi się prawdę powiedziawszy nieco trudniejsze niż sama CAPTCHA.
Go to the top of the page
+Quote Post
nieraczek
post 15.05.2009, 08:00:06
Post #8





Grupa: Zarejestrowani
Postów: 405
Pomógł: 6
Dołączył: 12.01.2007

Ostrzeżenie: (0%)
-----


Captcha jest beznadziejna, zwykle tam gdzie to jest to rezygnuje z rejestracji, chyba że bardzo mi zależy na rejestracji na danej stronie. Z jakich powodów ? Zz takich powodów, że zwykle muszę wpisywać kilka razy kod z obrazka bo zawsze się mylę, np. nie jestem w stanie odróżnić litery O od cyfry 0, litery I od cyfry 1 itd. Może to i chroni przed spambotami, ale ja zwykle rezygnuję z rejestracji w takich serwisach, bo nie jestem w stanie rozczytać co tam jest nabazgrane.

Ten post edytował nieraczek 15.05.2009, 08:00:51
Go to the top of the page
+Quote Post
pyro
post 15.05.2009, 11:51:12
Post #9





Grupa: Zarejestrowani
Postów: 2 148
Pomógł: 230
Dołączył: 26.03.2008

Ostrzeżenie: (0%)
-----


Cytat(nieraczek @ 15.05.2009, 09:00:06 ) *
Captcha jest beznadziejna, zwykle tam gdzie to jest to rezygnuje z rejestracji, chyba że bardzo mi zależy na rejestracji na danej stronie. Z jakich powodów ? Zz takich powodów, że zwykle muszę wpisywać kilka razy kod z obrazka bo zawsze się mylę, np. nie jestem w stanie odróżnić litery O od cyfry 0, litery I od cyfry 1 itd. Może to i chroni przed spambotami, ale ja zwykle rezygnuję z rejestracji w takich serwisach, bo nie jestem w stanie rozczytać co tam jest nabazgrane.


To sobie sciagnij captche od google, sa tam uzywane słowa a nie losowe litery


--------------------
ET LINGUA EIUS LOQUETUR IUDICIUM
Go to the top of the page
+Quote Post
pijanyadmin
post 15.05.2009, 12:23:17
Post #10





Grupa: Zarejestrowani
Postów: 128
Pomógł: 1
Dołączył: 24.10.2007

Ostrzeżenie: (0%)
-----


Nie ma captche od google, jest tylko cpatcha podobna do tej z google.
Go to the top of the page
+Quote Post
pyro
post 15.05.2009, 12:39:16
Post #11





Grupa: Zarejestrowani
Postów: 2 148
Pomógł: 230
Dołączył: 26.03.2008

Ostrzeżenie: (0%)
-----


Cytat(pijanyadmin @ 15.05.2009, 13:23:17 ) *
Nie ma captche od google, jest tylko cpatcha podobna do tej z google.


Miałem to na myśli winksmiley.jpg

link: http://code.google.com/p/cool-php-captcha


--------------------
ET LINGUA EIUS LOQUETUR IUDICIUM
Go to the top of the page
+Quote Post
pijanyadmin
post 15.05.2009, 12:48:12
Post #12





Grupa: Zarejestrowani
Postów: 128
Pomógł: 1
Dołączył: 24.10.2007

Ostrzeżenie: (0%)
-----


Poza tym, nieraczek to Ty nie masz konta praktycznie nigdzie? biggrin.gif Nawet emaila wp,gmail? To straszne... Poza tym nie widze problemu aby pisząc takie "bajery" wykluczyć znaki "o01l" itp. Przy stronie o cioci Krysi nie ma sensu pisać captcha, ale przy większych serwisach jest to wskazane.
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 14.08.2025 - 01:10