3.1 KiB
3.1 KiB
Task 15: Pre-auth лимит должен срабатывать ДО обращения к session store
Assigned to: Antigravity (Implementation Orchestrator)
Priority: MEDIUM (доступность / защита БД)
Date: 2026-08-21
Base SHA: 8e39ce0cbd809b9fb1666dce09905035bc493c10
Проблема
При флуде запросами с невалидными/фейковыми куками (randomayzer_session=<random>), запрос сначала совершал обращение к Session Store (prisma.session / БД), и только после этого проверял лимит. Таким образом, 300 запросов с фейковыми куками совершали 300 обращений к БД, создавая неограниченную нагрузку.
Scope
- В
SlidingWindowRateLimiter(src/lib/rate-limiter.ts):- Добавить read-only методы проверки лимита без списания токена:
isAllowed(key: string): boolean(илиpeek(key: string): boolean) — проверяет, не превышен ли лимит в текущем скользящем окне, не добавляя timestamp в историю.assertAllowedReadOnly(key: string): void(илиpeekAllowed(key: string): void) — выбрасываетRateLimitError, если лимит уже исчерпан, без модификации состояния.consume(key: string): void(илиcharge(key: string): void/ существующийcheck(key)/assertAllowed(key)) — списывает токен / добавляет timestamp.
- Добавить read-only методы проверки лимита без списания токена:
- В
requireAuthenticatedUser(src/lib/auth/auth-guard.ts):- До обращения к Session Store (независимо от наличия сессионной куки): выполнить read-only проверку
preAuthRateLimiter.assertCanAttempt('pre-auth:' + clientIp). Если лимит уже исчерпан — немедленно выбросить 429RateLimitErrorбез похода в Session Store / БД. - Если куки нет: списать токен в
preAuthRateLimiterи выбросить 401UnauthorizedError. - Если кука есть: обратиться в Session Store (
getSessionFromRequest(req)).- Если сессия не найдена / невалидна / истекла: списать токен в
preAuthRateLimiterи выбросить 401UnauthorizedError. - Если сессия валидна: вернуть
sessionUserбез списанияpreAuthRateLimiterтокенов.
- Если сессия не найдена / невалидна / истекла: списать токен в
- До обращения к Session Store (независимо от наличия сессионной куки): выполнить read-only проверку
- Дополнить
tests/pre-auth-rate-limit.test.ts:- 300 запросов с уникальными фейковыми куками ->
getSessionCalls <= 60, остальные 240 отсекаются с кодом 429 без обращения к БД. - 300 запросов без кук ->
getSessionCalls === 0. - Успешная аутентификация не расходует pre-auth токены.
- User-scoped изоляция сохраняется.
- 300 запросов с уникальными фейковыми куками ->