Квест → Как хакнуть форму
Прошли: 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