Files

21 lines
2.2 KiB
Markdown
Raw Permalink Normal View History

# Сериализация попыток входа по IP (изменение 027)
Находка № 7 из `docs/reviews/2026-09-26-codebase-review-2.md`, серьёзность — низкая. Выполняется вместе с 026 (тот же файл).
## Context
Изменение 024 сериализует попытки одного логина (`pg_advisory_xact_lock(hashtext(логин))`). Параллельные попытки **разных** логинов с одного IP проходят проверку лимита по IP
одновременно, и порог 20 можно превысить на степень параллелизма.
## Решение (`app/api/v1/auth.py`, `login`)
1. После блокировки по логину и до `_retry_after` — вторая блокировка `pg_advisory_xact_lock(hashtext('ip:' || ip))`, если `ip` известен.
Порядок всегда «логин, затем IP»: IP-блокировка берётся последней, поэтому цикл ожидания невозможен.
2. Использовать двухаргументную форму advisory-lock с отдельными пространствами ключей, чтобы исключить коллизии между логинами и IP:
`pg_advisory_xact_lock(<LOGIN_NS>, hashtext(name))` и `pg_advisory_xact_lock(<IP_NS>, hashtext(ip))`; константы пространств — в `auth.py` (например, 7031 и 7032).
3. Комментарий в коде: цена — попытки с одного IP (в том числе за NAT) обрабатываются по одной, время ответа при массовом входе растёт на время argon2.
## Файлы
`app/api/v1/auth.py`, `README.md` (одна фраза в абзаце «Вход»).
## Проверка
16 параллельных неверных входов на 16 разных несуществующих логинов с одного IP при заранее вставленных 15 неудачах этого IP → проверено не больше 5 паролей
(в `login_attempts` добавилось ≤ 5 записей), остальные — 429.