Как это работает?
Для того, чтобы пройти проверку анти-бота, пользователю предлагается кликнуть на кружок определенного цвета. Тут сразу можно добавить, что это всего лишь прототип, и выставляется на всеобщее обсуждения для того, чтобы хоть как-то сдвинуться с мертвой точки монополии капчи. Кружки рисуются на холсте (canvas). При этом в моем примере они рисуются прямо в JavaScript. В рабочем варианте предполагается рисовать их на стороне сервера, и на холст отрисовывать только готовую картинку.
Сам прототип целиком можно найти на гитхабе.
А тем временем я опишу основные методы, которые использовались для реализации:
1. Создадим некий массив цветов будущих кружочков.
this.colors = ["red", "green", "blue", "pink", "yellow", "orange", "violet"];
2. Генерируем сами кружочки.
generateObjects = function(g) { var used = []; var used_ = []; // перемешиваем цвета var colors = shuffle(self.colors); // выбираем случайное количество кружочков, но не менее трех var howMuch = rand(3, colors.length); for (var i = 0; i < howMuch; i++) { var centerX = rand(10, self.width); var centerY = rand(10, self.height); var radius = rand(10, 15); g.beginPath(); g.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); g.fillStyle = colors[i]; g.fill(); g.lineWidth = 1; g.strokeStyle = colors[i]; g.stroke(); used.push(colors[i]); used_.push({ x: centerX, y: centerY, // указываем радиус, он нам пригодится для определения пересечений r: radius }); } // выбираем случайный кружок и делаем его ответом на капчу var a = rand(0, howMuch - 1); self.active = used_[a]; return used[a]; };
3. Для того, чтобы определить пересечение нажатия и кружочка, используем два метода.
mouseReleased = function(dim) { // координаты нам пришли из lib/captcha_listener.js dim.x = dim.x - $(self.canvas).offset().left; dim.y = dim.y - $(self.canvas).offset().top; // сначала проверяем, был ли совершен клик на саму "капчу" if (self.inBounds(dim)) { // выводим координаты нажатия $(".captchaResult").val(dim.x + ":" + dim.y); // ну и так как это POC, проверяем и уведомляем пользователя, попал он по правильному кружочку или нет if (self.inCircle(dim)) { alert("nice!"); } else { alert("bot..."); } } };
Сама проверка inCircle()
inCircle = function(dim) { var a = self.active; // как и говорилось до этого, используем радиус для определения пересечений // NB! здесь по-хорошему должна использоваться формула окружности, я в свою очередь оставил вариант по проще var x0 = a.x - a.r; var x1 = a.x + a.r; var y0 = a.y - a.r; var y1 = a.y + a.r; if (x0 <= dim.x && dim.x <= x1 && y0 <= dim.y && dim.y <= y1) { return true; } else { return false; } };
И собственно вот так выглядит наша свежеиспеченная капча:
К сожалению, такая капча будет проблемой не только для ботов, но и для людей не различающих цвета.
С радостью выслушаю предложения по поводу капчи. Смело делайте форки, если идея понравилась. Напомню, что это лишь прототип того, что можно сотворить из этой идеи.
ссылка на оригинал статьи http://habrahabr.ru/post/177851/
Добавить комментарий