Регрессия: новый лимит check_username может блокировать обычный процесс регистрации

После недавнего изменения в PR #43042 запросы к /u/check_username.json ограничены до 10 запросов в минуту на один IP-адрес.

Похоже, это вызвало регрессию в стандартном процессе регистрации.

При создании нового аккаунта Discourse автоматически проверяет доступность имени пользователя. Пользователю не нужно многократно отправлять форму, чтобы превысить этот лимит. Просто ввод адреса электронной почты и имени пользователя, паузы во время набора, изменение имени пользователя или исправление опечатки могут привести к множественным запросам к /u/check_username.json.

После достижения лимита в форме регистрации отображается сообщение:

Вы выполняли это действие слишком много раз, пожалуйста, попробуйте позже.

Ошибка отображается непосредственно под полем имени пользователя и фактически блокирует пользователя от продолжения процесса до истечения срока действия ограничения частоты запросов.

Нет никаких указаний о том, сколько времени пользователю нужно ждать, и с точки зрения пользователя это выглядит так, будто выбранное имя пользователя или форма регистрации сломаны.

Шаги для воспроизведения

  1. Откройте форму регистрации как анонимный пользователь.
  2. Введите действительный адрес электронной почты.
  3. Несколько раз введите и измените имя пользователя, позволяя проверке доступности имени выполняться между изменениями.
  4. Продолжайте, пока количество вызовов /u/check_username.json не превысит 10 раз в течение одной минуты.
  5. В поле имени пользователя начинает отображаться ошибка ограничения частоты запросов:
    Вы выполняли это действие слишком много раз, пожалуйста, попробуйте позже.

Ожидаемое поведение

Обычный пользователь, заполняющий или исправляющий форму регистрации, не должен блокироваться внутренним ограничением частоты запросов, вызванным автоматическими проверками доступности имени пользователя.

Если ограничение частоты запросов необходимо для предотвращения злоупотреблений, пользовательский интерфейс регистрации должен деградировать плавно, а не отображать ошибку ограничения частоты и не препятствовать созданию аккаунта.

Фактическое поведение

Пользователь получает встроенную ошибку валидации в поле имени пользователя и не может продолжить работу в обычном режиме до истечения лимита.

Соответствующее изменение

Похоже, это было введено в:

PR #43042 – DEV: Rate limit check_username requests per IP

Текущая реализация использует:

RateLimiter.new(
  current_user,
  "check-username-#{request.remote_ip}",
  10,
  1.minute
).performed!

Сам пользовательский интерфейс регистрации может генерировать несколько проверок имени пользователя, поэтому лимит в 10 запросов в минуту может быть достигнут при легитимном взаимодействии.

Это может быть даже более проблематично для пользователей, находящихся за общим NAT/публичным IP-адресом, поскольку ограничитель работает на основе IP, а не на основе сессии.

Дополнительное наблюдение

У check_email также есть ограничитель в 10 запросов/минута/IP, но при превышении этого лимита он возвращает успешный ответ, а не выводит ошибку ограничения частоты запросов пользователю.

Поэтому имеет смысл, чтобы check_username вел себя аналогичным образом, или, альтернативно:

  • увеличить лимит;

  • сделать его настраиваемым;

  • не учитывать запросы на автозаполнение имени пользователя/автоматическую валидацию в той же корзине;

  • или обрабатывать ограничение частоты запросов на стороне клиента, не блокируя процесс регистрации.

    Я могу воспроизвести это на текущей установке Discourse, включая https://try.discourse.org/ после изменения из PR #43042.

1 лайк