Защита сайта от спамеров с использованием PHP. Практическое применение кода подтверждения с картинки.

Автор: Беляев Александр
Сайт Автора: wm-help.net
E-mail Автора: [email protected]
Дата написания: 26.10.2006

    В настоящее время множество хороших сайтов страдает от огромного потока рекламных объявлений или просто спама, который не добросовестные пользователи интернета пытаются расположить везде, где только это возможно: в гостевых книгах, форумах, каталогах и везде, где только можно оставить пару строк своего текста.

    Основным методом борьбы с явлением такого вида спама является создание всевозможных проверок на человечность, т.е. определения, кто вводил данные в форму, человек или программа. К таким проверкам можно отнести:

  • просьбу ввести в текстовое поле номер или слово с картинки
  • ввести ответ на загадку или какой-либо вопрос
  • нажать одну из нескольких кнопок (<input type="button">)
  • выбрать один из нескольких правильных ответов (<input type="radio">)
  • выбрать несколько ответов (<input type="checkbox">)

    Несмотря на столь значительный список методов борьбы со спамом, применяют обычно только первый пункт, т.е. используют изображение с текстом или цифрами.

    Алгоритм сверки данных в этом случае осуществляется несколькими способами:

  • В форме находится один и более скрытых элементов (<input type="hidden">) содержащих какие-либо значения и поле для ввода данных.
  • Генерируемое случайным образом значение сохраняется в БД и имеет небольшой срок жизни, при совпадении со значением из текстового поля находящегося. в форме эта запись удаляется.
  • Использование Cookies, т.е. сохранение правильного ответа у пользователя (крайне не удобно и не всегда работает).
  • В качестве кода подтверждения используются перемешанные числа текущей даты.
  • Предыдущий вариант, но разбавленный латинскими буквами.
  • Фантазия разработчиков безгранична…
  •     Нами будет рассмотрен самый простой способ борьбы со спамерами, т.е. цифровой код нанесенный на картинку, состоящий из перемешанной текущей даты. Такой код подтверждения будет действителен менее десяти минут, с момента его генерации. Он будет нанесен на картинку, причем каждый раз код будет разный, в разных местах картинки, под разным углом, на разном фоне и написан различными шрифтами. Для начала определимся, что именно мы будем использовать из даты, предлагаю использовать текущие: день недели, месяц, число, час, минуты (первую цифру) и день в году. На мой взгляд, это, неприступная защита для простых программ-регистраторов или их авторов, т.к. точно определить какие значения из даты используются для генерации кода подтверждения практически невозможно. Но если вам и этого окажется мало, то можно перемножить или сложить все значения, или для каждого дня недели использовать свой алгоритм вычисления, все зависит только от вашей фантазии.

        И так, начнем писать наш php-код, а то я уж слишком сильно углубился в теоретическую часть вопроса. Создаем новый php-файл и для начала напишем в нем функцию, которая будет "придумывать" код подтверждения из текущей даты, выглядеть она будет примерно так:

    function generate_code()
    {
        $week_day = date("w");              // день недели
        $day = date("d");                   // число
        $hours = date("H");                 // час
        $minuts = substr(date("H"), 0 , 1); // минуты (первая цифра)
        $mouns = date("m");                 // месяц
        $year_day = date("z");              // день в году
     
        $str = $week_day . $day . $hours . $minuts . $mouns . $year_day; // формируем результирующую строку
     
        $array_mix = preg_split('//', $str, -1, PREG_SPLIT_NO_EMPTY); // разбиваем сроку на символы и заносим их в массив
        srand ((float)microtime()*1000000); // запускаем генератор случейных чисел
        shuffle ($array_mix); // перемешиваем значения в массиве
        return implode("", $array_mix); // объединяем все значения массива в строку и возвращаем
    }

        Теперь, когда у нас уже готова функция для генерации цифрового кода подтверждения, можно написать функцию для генерации этого кода на изображении взятом из файла, а затем вывод получившейся картинки с кодом подтверждения в браузер. Выглядит эта функция так:

    function img_code()
    {
    // что бы не кэшировалась картинка
    header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");                     // дата в прошлом
    header("Last-Modified: " . gmdate("D, d M Y H:i:s", 10000) . " GMT"); // 1 января 1970
    header("Cache-Control: no-store, no-cache, must-revalidate");         // HTTP/1.1
    header("Cache-Control: post-check=0, pre-check=0", false);            // еще раз, для надежности
    header("Pragma: no-cache");                                           // HTTP/1.0
    header("Content-Type:image/png");
     
    $linenum = 2; // Число линий (для шума в картинке)
    $img_arr = array( // массив с именами файлов-фонов
                     "codegen.png",
                     "codegen0.png"
                    );
    $font_arr = array(); // массив со шрифтами
    $font_arr[0]["fname"] = "04B_24__.TTF";
    $font_arr[0]["size"] = 15;
    $font_arr[1]["fname"] = "Kiloton.ttf";
    $font_arr[1]["size"] = 9;
     
    $n = rand(0,sizeof($font_arr)-1); // выбираем шрифт
    $img_fn = $img_arr[rand(0, sizeof($img_arr)-1)]; // выбираем фон
     
    $im = imagecreatefrompng (code_dir . $img_fn); // загружаем фон
     
    for ($i=0; $i<$linenum; $i++) // шум в виде линий
    {
        $color = imagecolorallocate($im, rand(0, 255), rand(0, 200), rand(0, 255));
        imageline($im, rand(0, 20), rand(1, 50), rand(150, 180), rand(1, 50), $color);
    }
     
    $color = imagecolorallocate($im, rand(0, 200), 0, rand(0, 200)); // цвет текста
    imagettftext ($im, $font_arr[$n]["size"], rand(-4, 4), rand(10, 45), rand(20, 35), $color, code_dir.$font_arr[$n]["fname"], generate_code()); //сам текст в пределах картинки
     
    for ($i=0; $i<$linenum; $i++) // шум в виде линий
    {
        $color = imagecolorallocate($im, rand(0, 255), rand(0, 200), rand(0, 255));
        imageline($im, rand(0, 20), rand(1, 50), rand(150, 180), rand(1, 50), $color);
    }
     
    ImagePNG ($im); // вывод изображения
    ImageDestroy ($im); // Освобождаем память
    }

        Для того, что бы все работало, в начале php-скрипта пишем:

    define("code_dir", "my_codegen/");

    , а в конце

    img_code();

        Затем создаете папку my_codegen в той директории, в которой расположен php-скрипт – генератор изображений с кодом подтверждения, и создаете codegen.png и codegen0.png в Photoshope или другом графическом редакторе, копируете туда шрифты TrueType с именами Kiloton.ttf и 04B_24__.TTF. Все на этом генератор картинок завершен.

        Теперь нам нужна функция для проверки введенных данных, она будет реализована по тому же принципу что и generate_code, ее нужно поместить в отдельный php-скрипт, который будет осуществлять проверку введенных данных:

    function chec_code($code)
    {
        $code = trim($code);
     
        $array_mix = preg_split ('//', generate_code(), -1, PREG_SPLIT_NO_EMPTY);
        $m_code = preg_split ('//', $code, -1, PREG_SPLIT_NO_EMPTY);
     
        $result = array_intersect ($array_mix, $m_code);
    if (strlen(generate_code())!=strlen($code))
    {

        return FALSE;
    }

    if (sizeof($result) == sizeof($array_mix))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
    }

        В этот же файл, в конец добавьте функцию generate_code()

        И в заключении примерная схема реализации:

    <?php
    echo<<<END
    <form name="codegen">
        <p><img src="my_codegen.php" border="0"></p>
        <p><input type="text" name="code"></p>
        <p><input type="submit" name="send"></p>
    </form>
    END;


    function generate_code()
    {

    }
     
    function chec_code($code)
    {

    }
     
    if (isset($_GET['code']))
    {
    echo "Введенный код: " . $_GET['code'];
    if (chec_code($_GET['code']))
    {
    echo "<br>Верный код подтверждения!!!";
    }
    else
    {
    echo "<br>Неверный код подтверждения!!!";
    }
    }
    ?>

        Скачать данный php-скрипт защиты сайтов от спамеров с помощью изображения с кодом подтверждения можно здесь (https://wm-help.net/download/codegen.zip). В архиве есть пример с наглядной реализацией данного метода борьбы со спамерскими программами.

    Источник: https://wm-help.net/my-articles/article/protect-site.image-code.htmPage copy protected against web site content infringement by Copyscape
    Перепечатка данной статьи разрешается только при письменном(e-mail) разрешении автора (Беляева Александра Дмитриевича) и при полном сохранении исходного вида статьи (ссылки, авторские реферальные ссылки, e-mail'ы, форматирование текста, ...), а так же указания точных данных об авторстве (данные автора + прямая [без редиректа и не закрытая от индексации] ссылка на статью).
    В случае не выполнения данных правил, возможно применение «особых» мер, к нарушителям.

    Другие статьи из раздела "Защита сайта с PHP"
    Защита изображений на всем сайте. PHP+mod_rewrite
    Защита e-mail'ов пользователей от спамеров
    Защита сайта. Блокировка ip адреса
       Защита сайта от спамеров с использованием PHP. Практическое применение кода подтверждения с картинки.