
Буквально на днях DoctorDemon предложил интересный, на мой взгляд, вариант капчи. В комментариях к посту, мнения Хабраюзеров были разные и основным минусом выделяли простоту подбора для ботов. Я же заинтересовался и подумал – отчего бы не реализовать?
В процессе раздумий я пришел к волевому решению, что «лабиринтик» будем генерировать случайно каждый раз, чтобы усложнить жизнь надоедливым ботам.

Внимательный читатель заметит, что я отказался от других символов и слегка упростил структуру «лабиринта», оставив только перемещение на целую клетку – это упрощает генерацию и последующую навигацию по «лабиринтику». Для пущей красоты пути не пересекаются. Т.е. любой лабиринт мы можем представить в виде дерева, вершиной которого является точка начала, а детьми каждой вершины – точки, после следования по веткам «налево», «направо», «вверх» и «вниз».
Конечно, всё это упростило задачу ботов – но мне кажется, что лабиринтик благодаря этому выглядит дружелюбнее. Уменьшается время на генерацию лабиринта и облегчается процесс прохождения лабиринта для нормального посетителя.
Попробовать это в действии вы можете тут: http://star.nn.ru/
Теперь переходим к принципу работы.
Чтобы задача ботов отличалась от нахождения ответа на вопрос «введите 2+2» пришлось пойти на хитрость. После генерации лабиринта, он сохраняется в базе данных вместе с идентификатором сессии. Пока увлеченный пользователь движется к пункту «А» все его движения javascript-ом заносятся в скрытое поле формы. После прохождения появляется submit, нажав на который, имя комментатора, текст и проделанный путь отправляются на сервер. Уже на серверной стороне, тот самый лабиринт загружается из базы данных и старательный скрипт повторяет действия пользователя, следя за тем, чтобы мы не сбились с дороги, а в конце оказались в пункте «А». Если всё так и вышло – каптча пройдена и комментарий добавляется. Иначе, очевидно, что перед нами недоброжелатель и можно смело блокировать его, к примеру по IP –адресу (ну этого я делать не стал).
Однако, задача подбора не становится неразрешимой, да и тем более армия натренированных капча-проходителей обойдут любую защиту. Это первый минус.
Второй минус – нагрузка на сервер. Во-первых, сама задача генерации лабиринта требует ресурсов. Вдобавок, нам требуется как минимум 2 обращения к базе данных – когда мы лабиринт сохраняем, и когда загружаем. А вообще, желательно бы его потом ещё и стереть. Ну, тут можно, конечно, таскать лабиринт от сервера к клиенту и обратно. Можно и вовсе нагенерить несколько сот разных лабиринтов и выдавать их из базы случайно без генерации.
И в довесок – проблемы с «мобильными» посетителями и большой объём дополнительных данных.
P.S. Это всего-лишь набосок, не лишенный недостатков, сделанный в перерывах за чашками кофе.