Перебір (/invoices/1, /invoices/2...) і скрапінг шукають дані, які віддаються без достатніх перевірок, або просто вивантажують усе відкрите.
Перша лінія - авторизація. Кожен запис перевіряється політикою, а запити списків починаються від власника. Якщо цього немає, решта заходів лише гальмує витік.
Не розкривати існування: для чужих ресурсів - 404, а не 403 (Response::denyAsNotFound()), щоб перебір не відрізняв «чуже» від «немає».
Обмеження частоти з розумом:
RateLimiter::for('lookups', function (Request $request) {
return Limit::perMinute(10)
->by($request->user()?->id ?: $request->ip())
->after(fn (Response $response) => $response->status() === 404);
});
after() рахує лише 404 - звичайні користувачі не впираються в ліміт, а перебір швидко зупиняється.
Непередбачувані ідентифікатори (UUID, ULID) у публічних URL ускладнюють перебір, але не замінюють авторизацію.
Проти масового збору відкритих даних:
- пагінація з обмеженням розміру сторінки, без «віддати все»;
- ліміти для гостей суворіші, ніж для автентифікованих;
- захист на рівні CDN (WAF, challenge) для явних ботів - він дешевший за обробку в PHP;
- моніторинг: різкий ріст 404 з одного джерела - сигнал.
Докладніше в документації: Обмеження частоти на основі відповіді