Относительно CAPTCHA: Я бы рекомендовал не использовать CAPTCHA, если вам это действительно не нужно. Почему?
- это некрасиво.
- это раздражает ваших пользователей. Вы не должны заставлять их прыгать через обручи, чтобы использовать ваш сайт.
Есть несколько альтернатив, которые очень просты, могут быть очень эффективными и полностью прозрачными для (почти всех) пользователей.
Поля Honeypot : добавьте поле к формам с общим именем, например, «веб-сайт». Рядом с ним добавьте ярлык с надписью «Не пишите в этой коробке». Используя Javascript скрыть ввод и метку. Когда вы получаете отправку формы, если в поле что-то есть, отклоните ввод.
Пользователи с JS не увидят его и будут в порядке. Пользователи без JS будут просто следовать простой инструкции. Спам-боты влюбятся в него и раскроют себя.
Автоматический faux-CAPTCHA : Это похоже на выше. Добавьте поле ввода с надписью "Напишите 'Alex'" (например). Используя Javascript (и зная, что большинство автоматических спам-ботов не будут работать с JS), спрячьте поле и заполните его 'Alex'. Если в отправленной форме нет волшебного слова, игнорируйте ее.
Пользователи с JS не увидят его и будут в порядке. Пользователи без JS будут просто следовать простой инструкции. Спам-боты не будут знать, что делать, и вы можете игнорировать их ввод.
Это защитит вас от 99,9% автоматических спам-ботов. То, чего он не сделает, даже в малейшей степени, защитит вас от целенаправленной атаки. Кто-то может настроить своего бота, чтобы избежать приманки или всегда вводить правильное значение.
Относительно блокировки Brute Force: Очевидно, что решение на стороне сервера - единственный реальный способ сделать это. Для одного из моих текущих проектов я внедрил систему защиты от перебора, очень похожую на ту, которую вы описываете. Он был основан на этом Плагине защиты от грубой силы для CakePHP.
Алгоритм довольно прост, но поначалу немного сбивает с толку.
- Пользователь запрашивает какое-либо действие (например, сброс пароля)
- Пробег:
DELETE * FROM brute_force WHERE expires < NOW()
Пробег:
SELECT COUNT(*) FROM brute_force
WHERE action = 'passwordReset'
AND ip = <their ip address>
- Если число больше
X
, попросите их немного подождать.
В противном случае выполните:
INSERT INTO brute_force (ip, action, expires)
VALUES (<their ip address>, 'passwordReset', NOW() + Y minutes)
- Продолжите использовать функцию сброса пароля.
Это позволит пользователям пытаться сбросить пароль только X раз за Y минут. Настройте эти значения по своему усмотрению. Возможно 3 сброса за 5 минут? Кроме того, у вас могут быть разные значения для каждого действия: для некоторых вещей (например, для создания PDF) вы можете захотеть ограничить его до 10 за 10 минут.