Квест → Как хакнуть форму
Прошли: 77
В последнее время всё больше и больше моих работ на Laravel связано с созданием API. У меня есть свой класс для ограничения скорости, который я использовал, но у меня было ощущение, что есть способ сделать это чище. Неудивительно, что, когда Тейлор решил написать middlewere ограничения скорости для Laravel, он сделал это чище и лучше, чем у меня.
Если Вы незнакомы с ним, ограничения скорости — это инструмент, наиболее часто используемый в API, который ограничивает количество запросов за определённое время, которое любой человек (или ПО) могут сделать.
Это означает, что, например, если некий бот запрашивает какой-нибудь особо "тяжёлый" роут API, то ваше приложение не упадёт, т. к. после n-ной попытки он получит ответ 429: Too Many Attempts.
.
Обычно хорошо написанное приложение, которое реализует ограничение скорости, также отправляет три заголовка: X-RateLimit-Limit
, X-RateLimit-Remaining
, and Retry-After
(вы получите только Retry-After
, если вы достигли предела). В X-RateLimit-Limit
содержится максимальное количество запросов, которое вы можете сделать этим приложение за текущий период времени. В X-RateLimit-Remaining
— сколько запросов у вас осталось. И в Retry-After
— через сколько секунд вы можете отправить запрос ещё раз (Retry-After
также может содержать дату вместо количества секунд).
Примечание: каждое API выбирает свой промежуток времени для ограничения скорости. У GitHub это час, у Twitter — 15 минут. Этот middleware для Laravel имеет промежуток в минуту.
Итак, о новой функции в фреймворк laravel 5.2. Есть новый middleware throttle
, который вы можете использовать для этого. Давайте взглянем на нашу группу роутов для API:
Route::group(['prefix' => 'api'], function () { Route::get('people', function () { return Person::all(); }); });
Давайте применим throttle
к ней. По умолчанию стоит ограничение в 60 запросов в минуту и по достижению лимита доступ отключается до конца истечения минуты.
Route::group(['prefix' => 'api', 'middleware' => 'throttle'], function () { Route::get('people', function () { return Person::all(); }); });
Если вы сделаете запрос этому роуту api/people
, то вы увидите следующие строки в заголовках ответа:
HTTP/1.1 200 OK ... другие заголовки ... X-RateLimit-Limit: 60 X-RateLimit-Remaining: 59
Этот ответ означает следующее:
A) этот запрос завершился успешно (статус 200
)
B) вы можете запрашивать этот роут 60 раз в минуту
C) у вас осталось 59 запросов на данную минуту
Какой ответ мы получим, если мы вышли за ограничение скорости?
HTTP/1.1 429 Too Many Requests ... другие заголовки ... Retry-After: 60 X-RateLimit-Limit: 60 X-RateLimit-Remaining: 0
А сам ответ будет содержать строку: "Too Many Attempts."
Что, если бы мы попробовали еще раз через 30 секунд?
HTTP/1.1 429 Too Many Requests ... другие заголовки ... Retry-After: 30 X-RateLimit-Limit: 60 X-RateLimit-Remaining: 0
Тот же ответ, за исключением того, что таймер Retry-After
, который сообщает нам как долго ждать, опустился на 30 секунд.
throttle
Давайте сделаем немного настройки. Допустим, мы хотим ограничить его до 5 попыток в минуту:
Route::group(['prefix' => 'api', 'middleware' => 'throttle:5'], function () { Route::get('people', function () { return Person::all(); }); });
И если мы хотим изменить его таким образом, что если кто-то достигает предела, он не может снова отправить запрос в течение:
Route::group(['prefix' => 'api', 'middleware' => 'throttle:5,10'], function () { Route::get('people', function () { return Person::all(); }); });
Вот и все!
Код, которые это реализует, вы можете помотреть здесь: ThrottlesRequests.php