对于眼尖的读者,您可能已经注意到我们上一篇文章中调用configureRateLimiting
的方法。RouteServiceProvider
protected function configureRateLimiting()
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
}
这样做是限制用户每分钟的请求。默认设置为60
每分钟请求数。如果您需要修改请求的数量,您通常会在此处进行修改(即,将其从 更改为60
)100
。
正如您在代码中看到的,速率限制器是在RateLimiter
外观的for
方法中定义的。它接受一个速率限制器和一个返回限制配置的闭包。在这种情况下,这是路由的速率限制器api
,我们尚未介绍。
如果我们想要一个web
速率限制器怎么办?我们可以创建一个新的RateLimiter
并将其更改api
为web
.
protected function configureRateLimiting()
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
RateLimiter::for('web', function (Request $request) {
return Limit::perMinute(5)->by($request->user()?->id ?: $request->ip());
});
}
如果超出限制,429
则会将错误发送回用户。为了进行测试,我将速率限制更改为5
并刷新了页面,以便您可以看到响应。
如果我们刷新页面超过 5 次,则什么也不会发生。发生了什么?我们需要将throttle
中间件应用于我们想要限制的路由。
Route::middleware(['throttle:web'])->group(function () {
Route::get('/throttle-test-1', function() {
return "Throttle Test 1";
});
Route::get('/throttle-test-2', function() {
return "Throttle Test 2";
});
});
我们还没有覆盖middleware
,但我们很快就会覆盖。在此示例中,您只需将throttle:
后跟速率限制器的名称传递给该middleware
方法。第 5 次尝试后,我们收到以下消息。
对于那些跳过并检查api.php
路由文件的人,您会惊讶地发现throttle:api
那里并没有发生。
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
有一个auth:sanctum
中间件,但没有throttle:api
. 那么,api路由文件是如何工作的呢?很高兴你问了(不是真的)。打开app\Http\Kernel.php
。
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array<int, class-string|string>
*/
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* @var array<string, array<int, class-string|string>>
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array<string, class-string|string>
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
}
该文件包含所有各种不同的中间件定义以及它们的应用时间。如果开始向下扫描页面,您会发现以下受保护的属性。
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
在api
,您可以看到throttle:api
。如果我们想应用throttle:web
我们刚刚定义的速率限制器,我们可以将它添加到我们的web
数组中。
protected $middlewareGroups = [
'web' => [
'throttle:web',
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
现在,您的web
速率限制器已应用于所有web
路由。刷新任何路由 5 次,您将看到它将返回一个429
错误。
我将从文件中对此进行注释Kernel.php
并将web
速率限制器更改为100
. 您可以根据需要定义任意数量的速率限制器,并将它们应用于您选择的任何路由。不要太担心中间件和Kernel
文件;我们将在以后的文章中逐一介绍。