Защита Web-форм от автоматической обработки. Статьи. wb0.ru - Все для веб-мастера, on-line сервисы
Защита Web-форм от автоматической обработки

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

Требования: PHP>=4.0.6, GD >=2.0.

Данная статья написана по мотивам статьи Nathan Rohler "Security Images in PHP" опубликованной на сайте #Dev Shed 9 августа 2004 года.

Последнее время, в связи с распространяющейся эпидемией спама, веб-мастера, стали все чаще и чаще прятать адреса своей электронной почты (E-Mail). Многие стали использовать формы обратной связи. Но как оказалось, такую защиту можно обойти. И уже на сегодняшний день, существует огромное количество программ, предназначенных для рассылки спама, через формы обратной связи.

Наша задача - сделать так, чтобы сообщение вам смог отправить только "живой человек". Чаще всего, для этого используют небольшие картинки, на которых выводится текст. Пользователя просят продублировать этот текст в поле ввода. Если дублирование производится неверно, то форма не обрабатывается.

На сегодняшний день мне не знакомо ни одной программы, способной обойти такую защиту. Я даже на знаю ни одной программы, вообще, хоть как-то пытающуюся распознать содержимое картинки. По этому, можно смело сказать, что сегодня нет необходимости как-то искажать изображение на картинке. Но мы смотрим в будущее.

Генерация изображения

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

Основной недостаток такого алгоритма заключается в том, что существующую "подложку" можно быстро вычислить. А после этого вычесть из изображения, которое необходимо распознать и таким образом получить картинку с чистым текстом. А для распознания такого текста уже сегодня существует масса программ.

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

Я бы предложил следующий алгоритм:

  1. Создаем подложку (для этого можно использовать алгоритм построения фракталов)
  2. Добавляем помехи - несколько случайных линий, цвета основного текста.
  3. Выводим основной текст
  4. Самое интересное - увеличиваем изображение в неровное количество раз - например, в 1.7, в 1.6
  5. Уменьшаем изображение до оригинальных размеров
Увеличивать и уменьшать изображение необходимо с использованием сглаживания, иначе даже человек не сможет прочитать текста.

Если вам кажется, что рисовать фрактал слишком сложно, то можно нарисовать простую сетку.

Принцип работы механизма

При заходе пользователя на страницу с формой, мы создаем сессию и записываем в зарегистрированную переменную случайный код:

  1. session_start();
  2. session_register("secret_number");
  3. if (intval($_SESSION["secret_number"])<1000) {
  4.     srand(doubleval(microtime()));
  5.     $_SESSION["secret_number"]=rand(1000,9999);
  6.     }

После того как случайный текст сгенерирован, необходимо вывести форму:

  1. <form action="index.php" method="post">
  2. Ваш E-Mail:<br>
  3. <input type="text" name="email" value=""><br>
  4. <br>
  5. Введите код, который вы видите на картинке:<br>
  6. <input type="text" name="secretcode" value=""><br>
  7. <img src='code.php?<?=doubleval(microtime());?>'
  8.    width=101 height=26 vspace=5>
  9. <br><br>
  10. <input type="submit">
  11. </form>

Скрипт, обрабатывающий данные, отправленные при помощи формы, должен работать примерно следующим образом:

  1. session_start();
  2. session_register("secret_number");
  3.  
  4. if ($_SERVER["REQUEST_METHOD"]=="POST") {
  5.  
  6.     $error=0;
  7.     if ($_POST["secretcode"]!=$_SESSION["secret_number"] ||
  8.         intval($_POST["secretcode"])==0) $error=1;
  9.  
  10.     if ($error==0) {
  11.         $_SESSION["secret_number"]=rand(1000,9999);
  12.  
  13.         // Выполняем необходимые действия с данными
  14.         // ..
  15.         print "Hello ".htmlspecialchars(StripSlashes($_POST["email"]));
  16.         exit;
  17.         }
  18.  
  19.     if ($error==1)
  20.         print "Число с картинки введено неверно";
  21.     }
  22.  
  23. // Выводим форму повторно
  24. // ...

Генерация изображения

  1. // Регистрируем переменную
  2. session_start();
  3. session_register("secret_number");
  4. $_SESSION["secret_number"]=rand(1000,9999);
  5.  
  6. function mt() {
  7.     list($usec, $sec) = explode(' ', microtime());
  8.     return (float) $sec + ((float) $usec * 100000);
  9.     }
  10.  
  11. header("Content-type: image/png");
  12.  
  13. // создаем изображение
  14. $im=imagecreate(101, 26);
  15.  
  16. // Выделяем цвет фона (белый)
  17. $w=imagecolorallocate($im, 255, 255, 255);
  18.  
  19. // Выделяем цвет для фона (светло-серый)
  20. $g1=imagecolorallocate($im, 192, 192, 192);
  21.  
  22. // Выделяем цвет для более темных помех (темно-серый)
  23. $g2=imagecolorallocate($im, 64,64,64);
  24.  
  25. // Выделяем четыре случайных темных цвета для символов
  26. $cl1=imagecolorallocate($im,rand(0,128),rand(0,128),rand(0,128));
  27. $cl2=imagecolorallocate($im,rand(0,128),rand(0,128),rand(0,128));
  28. $cl3=imagecolorallocate($im,rand(0,128),rand(0,128),rand(0,128));
  29. $cl4=imagecolorallocate($im,rand(0,128),rand(0,128),rand(0,128));
  30.  
  31. // Рисуем сетку
  32. for ($i=0;$i<=100;$i+=5) imageline($im,$i,0,$i,25,$g1);
  33. for ($i=0;$i<=25;$i+=5) imageline($im,0,$i,100,$i,$g1);
  34.  
  35. // Выводим каждую цифру по отдельности, немного смещая случайным образом
  36. imagestring($im, 5, 0+rand(0,10), 5+rand(-5,5),
  37.     substr($_SESSION["secret_number"],0,1), $cl1);
  38. imagestring($im, 5, 25+rand(-10,10), 5+rand(-5,5),
  39.     substr($_SESSION["secret_number"],1,1), $cl2);
  40. imagestring($im, 5, 50+rand(-10,10), 5+rand(-5,5),
  41.     substr($_SESSION["secret_number"],2,1), $cl3);
  42. imagestring($im, 5, 75+rand(-10,10), 5+rand(-5,5),
  43.     substr($_SESSION["secret_number"],3,1), $cl4);
  44.  
  45. // Выводим пару случайных линий тесного цвета, прямо поверх символов.
  46. // Для увеличения количества линий можно увеличить,
  47. // изменив число выделенное красным цветом
  48. for ($i=0;$i<8;$i++)
  49.     imageline($im,rand(0,100),rand(0,25),rand(0,100),rand(0,25),$g2);
  50.  
  51.  
  52. // Коэффициент увеличения/уменьшения картинки
  53. $k=1.7;
  54.  
  55. // Создаем новое изображение, увеличенного размера
  56. $im1=imagecreatetruecolor(101*$k,26*$k);
  57.  
  58. // Копируем изображение с изменением размеров в большую сторону
  59. imagecopyresized($im1, $im, 0, 0, 0, 0, 101*$k, 26*$k, 101, 26);
  60.  
  61. // Создаем новое изображение, нормального размера
  62. $im2=imagecreatetruecolor(101,26);
  63.  
  64. // Копируем изображение с изменением размеров в меньшую сторону
  65. imagecopyresampled($im2, $im1, 0, 0, 0, 0, 101, 26, 101*$k, 26*$k);
  66.  
  67. // Генерируем изображение
  68. imagepng($im2);
  69.  
  70. // Освобождаем память
  71. imagedestroy($im2);
  72. imagedestroy($im1);
  73. imagedestroy($im);

Дата публикации: 30.08.2008

Статьи по теме:

   Ваш псевдоним:
Ваш комментарий:

Календарь событий


Новости Интернет


Поиск





Последний пересчет

тИЦ:07 Окт 15
PR:09 Дек 13

Наши партнеры

wservices.ru - регистрация доменов, Whois-сервисы Смайлы на все случаи жизни


 
Copyright © 2006-2024, wb0.ru