Как заблокировать ссылку от вредоносных посетителей бота?
Я создаю сайт регистрации событий. Когда кто-то нажимает на ссылку:
<a href="/reserve/10" rel="nofollow">Reserve id=10 event</a>
Система блокирует это событие на десять минут для этого посетителя. В этом случае никто не может зарезервировать это событие в следующие десять минут. Если оплата произведена в это время, все в порядке, иначе событие снова разблокируется. Надеюсь, идея понятна.
ПРОБЛЕМА: Когда бот (гугл-бот, злонамеренный бот или злой клиентский скрипт:P) заходит на эту страницу, он видит эту ссылку. Затем он заходит на страницу. Тогда замок сделан...
Также, если кто-то посещает рекурсивно: / Reserve/1, / Reserve/2, / Reserve/3, ... Он может заблокировать все события.
Я думал о создании случайного md5
Строка для каждого события. В этом случае каждое событие имеет (рядом с id
) уникальный код, например: 1987fjskdfh938hfsdvpowefjosidjf8243
Далее я могу перевести библиотеки, чтобы работать так:
<a href="/reserve/1987fjskdfh938hfsdvpowefjosidjf8243" rel="nofollow">
Reserve
</a>
В этом случае я могу предотвратить блокировку "грубой силы". Но ссылка все еще видна для ботов.
Тогда я подумал о вводе капчи. И это решение. Но капчи... не так уж хороши в плане удобства использования и пользовательского опыта.
Я видел несколько сайтов с таким механизмом бронирования. Они защищены? Может быть, есть простое решение ajax / javascript, чтобы боты не читали это как чистый текст? Я думал о:
<a href="/registerthisvisitorasbot" id="reserve">Reserve</a>
<script type="text/javascript">
$('#reserve').click(function(e) {
e.preventDefault();
var address = ...;
// something not so obvious to follow?
// for example: md5(ajaxget(some_php_file.php?salt=1029301))
window.location('/reserve/' + address);
});
</script>
Но я не уверен, что мне делать, чтобы боты не вычисляли его. Я имею в виду, что глупые боты не смогут даже следить за javascript или jquery, но иногда кто-то хочет что-то уничтожить, и если источник очевиден, это может быть разбито на несколько строк кода. И вся база данных событий будет заблокирована без возможности резервирования ни для кого.
2 ответа
CRFS + AJAX POST + EVENT TOKEN генерируется при каждой загрузке.
Резюме: не полагайтесь на запросы GET, особенно через a
элементы.
И лучше, если вы добавите некоторые ограничения скорости блоков событий (например, по IP).
РЕДАКТИРОВАТЬ: (это основной эскиз)
- заменить все
href="..."
сdata-reservation-id=ID
- делегат
click
на родительском элементе дляa[data-reservation-id]
- в обратном вызове просто сделайте POST Ajax-вызов API
- в ограничениях скорости проверки конечной точки API с использованием IP, например
- если OK, заблокируйте событие и верните OK, если нет, верните ошибку.
Специфичные для IP максимальные одновременные бронирования
Резюме: зависит от того, что многие простые боты работают с одного хоста. Ограничьте количество одновременных бронирований для хоста.
Базовый эскиз:
- Храните запрашивающий IP вместе с резервированием
По запросу резервирования подсчитайте IP-адреса, которые имеют незавершенное резервирование.
SELECT Count(ip) FROM reservations WHERE ip=:request_ip AND status=open;
Если число превышает определенный порог, заблокируйте бронирование.
(в основном это расширение пункта 4, приведенного в отличном ответе Аветиста)