Как заблокировать ссылку от вредоносных посетителей бота?

Я создаю сайт регистрации событий. Когда кто-то нажимает на ссылку:

<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).

РЕДАКТИРОВАТЬ: (это основной эскиз)

  1. заменить все href="..." с data-reservation-id=ID
  2. делегат click на родительском элементе для a[data-reservation-id]
  3. в обратном вызове просто сделайте POST Ajax-вызов API
  4. в ограничениях скорости проверки конечной точки API с использованием IP, например
  5. если OK, заблокируйте событие и верните OK, если нет, верните ошибку.

Специфичные для IP максимальные одновременные бронирования

Резюме: зависит от того, что многие простые боты работают с одного хоста. Ограничьте количество одновременных бронирований для хоста.

Базовый эскиз:

  • Храните запрашивающий IP вместе с резервированием
  • По запросу резервирования подсчитайте IP-адреса, которые имеют незавершенное резервирование.

    SELECT Count(ip) FROM reservations WHERE ip=:request_ip AND status=open;
    
  • Если число превышает определенный порог, заблокируйте бронирование.

(в основном это расширение пункта 4, приведенного в отличном ответе Аветиста)

Другие вопросы по тегам