CAPTCHA модуль для Perl

Мотивация

Изначально гостевая книга этого сайта была написанная с верой в идеальность мира и честность всех в нём живущих ;-) . К сожалению мир не идеален, и не все в нём честны, потому через некоторое время гостевая оказалась буквально завалена "горячими" предложениями от самых различных ботов. Разумеется напрашивается очевидный вывод - нужно поставить CAPTCHA.
Сайт использует Perl, и я стал искать подходящий вариант реализации на этом языке. Поискав в интернете я не нашёл ничего подходящего моим условиям: простота использования и настройки, минимум зависимостей от других модулей, опрятность кода и очевидность принципов работы.
В итоге написал свою реализацию взяв за основу самую простую идею CAPTCHA отсюда (спасибо авторам), кроме того оттуда же взят набор изображений используемых для проверки.
Реализация представляет собой Perl-класс содержащийся в модуле, что значительно упрощает его использование в уже существующем коде (см. пример). Кроме того выполнен ряд улучшений: например код ориентирован на выполнение в любом окружении (как CGI, так и mod_perl) - все необходимые для работы данные передаются в код при инициализации объекта класса NPCaptcha Фактически код переписан с нуля.

Принцип

Выбранная мною реализация базируется на принципе определения IP адреса пользователя и отдачи браузеру уже готовых изображений хранящихся в каталоге заданном при создании объекта класса. Имена файлов изображений без расширения соответствуют тому что на них отображено. Например изображение с именем файла JWBV.gif будет содержать буквы JWBV. Имея IP адрес удалённого пользователя и значение CAPTCHA полученное из имени файла, скрипт сохраняет локально информацию о том какое значение было отправленно данному IP адресу. В случае получения ответа от удалённого пользователя содержащего значение CAPTCHA скрипт проверяет создана-ли запись для этого IP адреса, если создана - проверка пройдена.
Хоть принцип очень прост, но как показывает практика - достаточно надёжен, даже учитывая вероятность работы нескольких пользователей из под одного IP адреса. Во всяком случае для небольших проектов. С момента установки CAPTCHA в моей гостевой не появилось ни одной новой записи от бота :-).

Алгоритм

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

  1. Скрипт считывает имена всех файлов изображений использующихся для проверки из каталога заданного при его старте.
  2. Выбирается случайный файл из полученного списка и во временной директории создаётся пустой временный файл с именем (IP-адрес-пользователя)-(имя-картинки-без-расширения).captcha.
  3. Файл считывается и отдаётся в браузер пользователя.
  4. Кроме того в браузер пользователя отдаётся cookie с значением равным его IP адресу.

Вторая часть алгоритма скрипта запускается после того как пользователь распознаёт значение на рисунке и отправляет форму с данными на сервер.

  1. Скрипт получает значение введённое пользователем и его адрес, после чего генерирует имя файла: (IP-адрес-пользователя)-(значение-введённое-пользователем).captcha
  2. Проверяет существует-ли файл с таким именем во временном каталоге, в который ранее была произведена запись.
  3. Если существует - удаляет этот файл и возвращает в вызвавшую программу значение "истина".
  4. Если не существует - проверяет наличие файла (значение-из-cookie)-(значение-введённое-пользователем).captcha, если существует - удаляет файл и возвращает в вызвавшую программу значение "истина".
  5. Иначе - возвращает значение "ложно".

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

Методы и параметры

Ниже описаны методы Perl-класса и параметры принимаемые конструктором при инициализации объекта.

  • NPCaptcha::new - конструктор класса, должен быть обязательно вызван перед использованием объекта. Хеш параметров использует следующие ключи:
    imagesdir - каталог содержащий файлы изображений CAPTCHA. По умолчанию - './images'
    tmpdir - каталог для записи временных файлов. По умолчанию - '/tmp'
    timeout - задаёт время (в секундах) спустя которое временные файлы считаются устаревшими для проверки и удаляются. По умолчанию - 600 секунд (10 минут).
    extensions - список расширений файлов с изображениями. По умолчанию - gif
    remoteAddr - задаёт IP удалённого пользователя. Определяется либо через функции mod_perl, либо через переменную $ENV{REMOTE_ADDR}. Не имеет значения по умолчанию.
    cookieName - имя cookie использующейся для отправки IP адреса в браузер пользователя. По умолчанию - 'captcha_rcpt'.
    cookieValue - значение cookie полученное каким-либо образом (например через $ENV{HTTP_COOKIE} или fetch CGI::Cookie).
    captchaValue - собственно значение CAPTCHA введённое пользователем в WEB-форму.
  • NPCaptcha::clearOld - удаление устаревших временных файлов. Вызывается автоматически из конструктора.
  • NPCaptcha::getImage - метод возвращающий считанное из файла изображение. Полученное значение можно выдать в браузер любым стандартным для данного случая методом. Например print $obj->getImage() в CGI или $r->print($obj->getImage()) в mod_perl. Не имеет параметров.
  • NPCaptcha::getCookie - возвращает в вызвавший скрипт строку вида:
    captcha_rcpt=(IP-адрес-пользователя); expires=Sun Jan 31 02:21:59 2010; path=/
    Должна быть вызвана до первого вывода HTML кода в скрипте, потому что эту строку нужно передать в браузер пользователя как cookie. Не имеет параметров.
  • NPCaptcha::check - функция выполняющая провеку введённого пользователем значения. Возвращает истину если проверка прошла успешно, иначе - ложь. Не имеет параметров.

Пример использования

Модуль NPCaptcha.pm должен находиться в одном из стандартных каталогов Perl-модулей, либо в коде скрипта должна использоваться директива:
use lib qw(/путь/к/каталогу/с/модулем);
Ниже приведён простейший пример использования CAPTCHA для защиты формы от автозаполнения ботами. Состоит из двух частей, первая часть - скрипт отдающий изображения в браузер пользователя:

Вторая часть - скрипт создающий форму защищённую от автозаполнения:

То как это выглядит и работает на практике:



Если у Вас возникли какие-либо замечания/предложения/пожелания по поводу данной статьи, то - предлагаю их сообщить по , либо высказать в гостевой.




Вернуться в "Разное"