as_snipercaptcha: CSS/DHTML (без GD-библиотек) CAPTCHA класс
as_snipercaptcha.php содержит PHP класс (CSniperCaptcha) для распространенной задачи, известной под абревиатурой CAPTCHA -
защиты интерактивных сайтов и форм от спам-роботов.
В отличие от большинства аналогичных CAPTCHA - движков, здесь не используются графические библиотеки генерации изображений (типа GD)
и не создается картинок с искаженными буквами и цифрами для распознавания человеком
(подобных классов в Сети достаточно).
|
Основная идея проста : пользователь (посетитель сайта) не вводит увиденные буквы/цифры в специально отведенное INPUT - поле,
вместо этого он видит на экране таблицу (сетку) из нескольких строк и столбцов, где одна из ячеек "подсвечена" специальной картинкой-указателем.
Он щелкает по этой ячейке мышью, в ответ указатель переходит на другую ячейку. Т.е. "кодовое слово" в нашем случае состоит из
верной последовательности выбранных ячеек.
В ответ на каждое нажатие (клик) мыши браузер отправляет ответ (ID ячейки) на сервер с помощью AJAX-запроса,
дожидается ответа, в котором содержатся координаты следующей цели, в которую надо "попасть".
Когда вся последовательность выполнена, с сервера приходит ответ о том, пройден или нет тест на "человечность" пользователя.
При желании Вы можете соответствующим Javascript-кодом обработать ответ и выполнить определенные действия на форме клиента.
|
Установка as_snipercaptcha
-
Скачав дистрибутивный zip-файл, распакуйте его в любую папку.
В заголовках скриптов, которые будут использовать наш класс, не забудьте вписать
require_once('as_snipercaptcha.php');
Указывать ли путь к файлу, как всегда зависит от того, куда Вы скопируете модуль.
Если на Вашем сайте уже используется фреймворк jQuery, рекомендуется использовать jquery-версию класса -
as_snipercaptcha_j.php. Необходимость в файле as_jsfunclib.js в этом случае отпадает. К тому же jQuery-версия класса
может обладать лучшей совместимостью с разными браузерами.
-
Перенесите/скопируйте файлы изображений (*.png, *.gif) в Вашу основную папку "images" на сайте, и "путь" к папке
задайте в константе IMGPATH (либо просто положите файлы в один каталог с Вашим скриптом) :
define('IMGPATH','allimages/');
Файл captchasight.png - это "маркер", которым помечается очередная ячейка выбора.
cap_progress.png нужен для отрисовки столбика "термометра", показывающего прогресс процедуры проверки.
-
Для формирования AJAX-запросов нам понадобится библиотека функций as_jsfunclib.js.
Поэтому скопируйте/перенесите этот файл в свою папку с js-скриптами либо в текущую папку.
Если файл будет в другой папке, не забудьте указать путь в методе DrawRefs() (см.ниже)
-
Стили, используемые при отрисовке решетки, вынесены в отдельный файл as_captchastyles.css - оставьте его
в рабочей папке или перенесите в свою папку для стилей - в этом случае укажите путь к ней при вызове метода
DrawRefs() (см.ниже).
Использование класса CSniperCaptcha
CSniperCaptcha генерирует небольшую HTML таблицу (или "решетку"), которая может содержать переменное число строк,столбцов,
а также переменную ширину-высоту одной ячейки.
Эти размерности могут быть жестко заданы Вами при вызове конструктора класса.
Если их не задать, эти значения будут выбраны случайным образом из диапазонов 3...6 строк и 4...10 колонок.
Случайный выбор призван затруднить обход CAPTCHA-защиты возможным спам-роботом или другим модулем "распознавания".
Вот как все работает :
-
Когда сетка для CAPTCHA движка готова и выведена браузером на экран, вычисляются ее координаты и посылаются на сервер
с помощью AJAX-вызова.
-
Получив эти координаты, сервер начинает последовательность проверки: он поочередно выбирает (случайным образом) следующую
ячейку, которая должна быть "кликнута" пользователем, и посылает ее вычисленные координаты в ответе клиенту.
Координаты вычисляются исходя из переданного положения решетки, ее размерности и ширины-высоты одной ячейки.
-
Клиент, получив координаты очередной ячейки, передвигает DOM-элемент "Image" в указанное место и ожидает щелчка мышью.
- Посетитель сайта щелкает по указанной ячейке, ее id отправляется на сервер.
- Когда все NN шагов выбора сделаны, и сервер получает последний ответ, он проверяет корректность ответов
и запоминает результат в наборе сессионных переменных, а также отправляет клиенту в последнем ответе.
Если Вы подготовите свои Javascript-функции для обоих случаев (CAPTCHA-тест пройден, провален),
их имена можно передать в класс, и тогда они будут выполнены соответственно при успешном или "проваленном" тесте.
Например, можно показать изначально скрытые поля ввода текста, или разблокировать кнопки и др.элементы ввода.
Функции будут вызваны сразу по получении ответа от сервера на последний выбор ячейки "проверочной" решетки.
Приведем простейший пример работы с классом. (Решетка для CAPTCHA-теста будет сгенерирована со случайным числом строк
и столбцов, и размером ячейки).
require_once('as_snipercaptcha.php');
$captcha = new CSniperCaptcha();
// вывести основной HTML код, включая начальные теги формы - <FORM ...> и необходимые поля ввода
CSniperCaptcha::DrawRefs(); // вывожу ссылки на используемые CSS и js файлы
$captcha->Draw(); // отображается опросная решетка
//... теперь вывести кнопку SUBMIT и закрывающие теги формы </FORM>
$captcha->DrawJsCode(); // выводятся сопутствующие javascript-функции
// остальной HTML код ...
CSniperCaptcha - список методов
CSniperCaptcha($codelen=4, $submitid='', $jscode_success='',$jscode_fail='', $reinit=false) - конструктор класса.
Параметры:
- $codelen число "кликов" в последовательности проверки (длина кодового слова)
- $submitid идентификатор (id) кнопки "submit". Если параметр передан в конструктор, эта кнопка получит состояние "разблокирована"
при успешном окончании проверки. Понятно, что в этом случае надо не забыть вывести у кнопки начальный атрибут DISABLED.
- $jscode_success - Javascript код (обычно имя функции со скобками "()" ), который должен быть выполнен
при успешном прохождении теста, ДО нажатия кнопки submit и отправки формы на сервер.
- $jscode_fail - Javascript код (обычно имя функции со скобками "()" ), который должен быть выполнен
при непройденном тесте, ДО нажатия кнопки submit и отправки формы на сервер.
- $reinit - 1 (цлое число, или true) или Javascript код. Любой непустой параметр включает вывод картинки-ссылки,
по нажатию которой captcha сбрасывается в начальное состояние, и ползователь может повторить процесс валидации.
Если в параметре передать строку, CSniperCaptcha интерпретирует ее как javascript код, который будет дополнительно выполнен
при сбросе "капчи" (например, если нужно убрать строку о проваленном captcha-тесте).
В качестве картинки "сброс" используется файл "captcha_init.gif", включенный в дистрибутив (меняйте под свою цветовую схему сайта).
Дополнительный текст приглашения к "сбросу" может быть задан в глобальном ассоциативном массиве, $sitestrings['captcha_init'].
SetServerScript($uri) - этот метод задает имя (URI) серверного скрипта, выполняющего проверку CAPTCHA теста.
По умолчанию весь обмен во время проверки ведется с тем же скриптом, который вывел форму.
Параметры:
- $uri - имя файла скрипта на сервере, который будет обрабатывать AJAX запросы от клиента и посылать ответы
DrawRefs($csspath='',$jspath='') - метод формирует и выводит <STYLE> и <SCRIPT> теги
со ссылками на файлы captcha_styles.css и as_jsfunclib.js, используемые в классе (входят в дистрибутив).
Если Вы перенесете все стили из прилагаемого файла captcha_styles.css в централизованный набор, используемый на всем сайте,
и потому не хотите выводить ссылку на css, передайте false в параметр $csspath.
Аналогично - для $jspath.
Параметры:
- $csspath - путь к файлу captcha_styles.css
- $jspath - путь к файлу as_jsfunclib.js
SetBufferedOutput($buffered=true) - задает режим "буферизованного" вывода, при котором весь сгенерированный
HTML код не идет в поток клиенту. Вместо этого все методы (Draw(), DrawJsCode(), DrawRefs())
возвращают соответствующий HTML код.
Это необходимо, когда разработчик сначала собирает всю HTML страницу в памяти, и только потом выводит
ее в поток клиенту.
Параметр $buffered - необязательное значение режима вывода, (логическое true|false или целое).
По умолчанию true. False (или 0) задает режим "небуферизованного вывода".
Draw($width=0, $height=0, $cellsize=0, $tovar=0) - метод формирует (и выводит) HTML код CAPTCHA-решетки.
Параметры:
- $width - Число колонок в решетке. Если ноль, выбирается случайным образом в диапазоне 4-10
- $height - Число строк в решетке. Если ноль, выбирается случайным образом в диапазоне 3-6
- $cellsize - размер (в пикселах) одной ячейки. Если ноль, выбирается случайным образом в диапазоне 10-17.
Замечание: не задавайте слишком маленький размер ячейки. Чтобы "подсветить" ячейку, подлежащую выбору,
поверх нее выводится картинка-маркер, имеющая размер 7x7 точек. Если она полностью накроет ячейку таблицы, "щелчок" по ней станет
невозможным, и пользователь никогда не пройдет теста !
- $tovar : по умолчанию HTML код немедленно выводится в поток клиенту. Если нужно отложить вывод (сделать это позже самостоятельно),
передайте непустое значение параметра $tovar. В этом случае вместо немедленного вывода метод Draw() вернет сгенерированный код.
Рекомендуется пользоваться методом SetBufferedOutput() - он включает буфекризованный ввод для ВСЕХ методов.
DrawJsCode($autostart=1) - этот метод выводит Javascript-скрипты необходимые для работы класса.
Вызывать это метод нужно после вывода формы с кодом CAPTCHA (т.е. после вывода кода, сгенерированного методом Draw()).
Исключение составляет случай "отложенного" старта процедуры проверки (см. параметры)
Параметры:
- $autostart :
По умолчанию сразу будет вызвана внутренняя функция, стартующая процесс проверки кода - SendCaptchaChecking().
Если нужно стартовать его позже (например, предварительно вывести еще какой-либо HTML-код, и только после полной его загрузки клиенту -
для этого можно занести вызов SendCaptchaChecking() в свойство onLoad документа),
вызывайте этот метод с нулевым (false или 0) параметром:
$captcha->DrawJsCode(0);
Полный пример использования
Мы будем выводить решетку CAPTCHA со случайными размерами.
Длина кодового слова - 5 (пользователь должен будет последовательно выбрать 5 ячеек из решетки).
Когда проверка закончится, кнопка отправки SUBMIT должна бвть автоматически разблокирована.
(Заметьте, что мы выводим ее с начальным тегом DISABLED).
require_once('as_snipercaptcha.php');
$captcha = new CSniperCaptcha(5, 'btn_submit'); // here SESSION is started, so NO HTML output before this !
// т.к. этот же скрипт принимает данные по нажатию SUBMIT, здесь же включаем блок обработки формы:
if(!empty($_POST)) {
if($captcha->CheckPassed()){
// process user data (publish to the database etc.
PublishNewMessage(); // Your function that does a job
echo "Спасибо, Ваше сообщение добавлено !";
}
else {
echo "Вы робот, до свидания";
}
exit;
}
CSniperCaptcha::DrawRefs(); // вывожу ссылки на CSS и js файлы
// выводим HTML код, стартующий FORM тег
// и все поля ввода (TEXTAREA и др.) без кнопки 'submit'
echo "Отправка сообщения";
$self = $_SERVER['PHP_SELF'];
CSniperCaptcha::DrawRefs('my_css/','my_js/'); // вывожу ссылки на используемые CSS и js файлы
echo "<FORM action='$self' method='POST' name='myform'>";
echo "<TEXTAREA name='messagetext' style='width:100%; height:120px'></TEXTAREA><br />";
$captcha->Draw();
echo "<input type='SUBMIT' id='btn_submit' name='btn_submit' value='Submit message' DISABLED />
echo "</FORM>";
$captcha->DrawJsCode();
//... вывод остального HTML кода
Вы можете использовать AJAX (XmlHTTPRequest) для получения от клиента данных с формы
(данные отправляются, и выводится результат без полной перерисовки всего экрана),
Ваш серверный backend php скрипт до обработки данных должен проверить,
прошел ли пользователь тест CAPTCHA :
// backend for processinbg posted data
require_once('as_snipercaptcha.php');
$captcha = new CSniperCaptcha();
if($captcha->CheckPassed()) {
PublushFormData($_POST); // здесь данные заносятся в базу и т.д.
echo "Спасибо, сообщение сохранено"; // ajax response will go to the client
}
else echo "Ошибка, тест CAPTCHA не пройден";
История (версии)
1.03.007 (10.12.2008)
- Добавлен модуль, использующий jQuery, as_snipercaptcha_j.php
- некоторые улучшения кода
1.03.006 (03.12.2008)
- Запросы пользователей: когда меняются размеры окна (или юзер изменяет размер букв в Mozilla FF, нажимая CTRL+, CTRL-),
captcha автоматически выполняет ре-инициализацию с подстройкой под новые координаты капча-решетки.
- Новый параметр в конструкторе, $reinit, включающий фичу "сброса" самим пользователем.
1.02.004 (10.05.2008)
- Исправлена проблема совместимости с FireFox (возникала при наличии в теге <!DOCTYPE...> ссылки на DTD файл)
1.0.001 (28.02.2008)