Laravel:如何仅对未认证API用户启用请求限流?
Laravel API 仅对未认证用户启用请求限流的实现方案
刚好之前做项目遇到过一模一样的需求,给你分享两种靠谱的实现方式,看哪种更适配你的业务场景:
方案一:拆分API路由组(逻辑清晰,推荐)
这种方式是把未认证和已认证的API路由分开,分别绑定不同的中间件组,精准控制限流范围。
步骤1:修改Kernel中的中间件组配置
打开app/Http/Kernel.php,在$middlewareGroups里新增一个专门给未认证用户用的api:guest组,把限流规则放在这里;原api组去掉限流,留给已认证用户使用:
protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, // \Illuminate\Session\Middleware\AuthenticateSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'api' => [ // 移除原throttle,仅保留必要的绑定替换中间件 \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'api:guest' => [ // 未认证用户的限流规则:每分钟240次请求 'throttle:240,1', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ];
步骤2:拆分API路由
打开routes/api.php,把路由分成未认证和已认证两组,分别绑定对应的中间件:
use App\Http\Controllers\AuthController; use Illuminate\Http\Request; // 未认证用户可访问的路由(登录、注册等),使用api:guest中间件组 Route::middleware('api:guest')->group(function () { Route::post('/login', [AuthController::class, 'login']); Route::post('/register', [AuthController::class, 'register']); // 其他公开API路由都放这里 }); // 已认证用户专属路由,使用api+auth:api中间件组(无限制) Route::middleware(['api', 'auth:api'])->group(function () { Route::get('/user', function (Request $request) { return $request->user(); }); // 所有需要登录才能访问的API路由放这里 });
方案二:自定义限流中间件(更灵活)
如果不想拆分路由,也可以自定义一个中间件,自动判断用户是否认证,仅对未认证用户触发限流。
步骤1:生成自定义中间件
执行Artisan命令生成中间件:
php artisan make:middleware ThrottleUnauthenticatedUsers
步骤2:编写中间件逻辑
打开app/Http/Middleware/ThrottleUnauthenticatedUsers.php,继承Laravel原生的限流中间件,重写handle方法:
<?php namespace App\Http\Middleware; use Illuminate\Routing\Middleware\ThrottleRequests; class ThrottleUnauthenticatedUsers extends ThrottleRequests { public function handle($request, \Closure $next, $maxAttempts = 60, $decayMinutes = 1) { // 如果用户已认证,直接跳过限流 if ($request->user()) { return $next($request); } // 未认证用户,执行原生限流逻辑 return parent::handle($request, $next, $maxAttempts, $decayMinutes); } }
步骤3:注册中间件别名
回到app/Http/Kernel.php,在$routeMiddleware里注册自定义中间件的别名:
protected $routeMiddleware = [ // 其他原有中间件... 'throttle.guest' => \App\Http\Middleware\ThrottleUnauthenticatedUsers::class, ];
步骤4:替换原API中间件组的限流规则
修改$middlewareGroups里的api组,把原throttle:240,1替换成自定义的throttle.guest:240,1:
'api' => [ 'throttle.guest:240,1', \Illuminate\Routing\Middleware\SubstituteBindings::class, ],
这样所有API路由都会通过这个自定义中间件,自动识别用户状态,仅对未认证用户执行限流。
两种方案都能实现你的需求,第一种拆分路由的方式逻辑更直观,适合路由划分清晰的项目;第二种自定义中间件的方式更灵活,适合不想改动现有路由结构的场景。
内容的提问来源于stack exchange,提问作者Aontaigh
相关产品推荐
相关产品推荐

