我可以限制每月的计划 API 调用和每分钟/小时的 API 调用吗?

我想使用 Laravel Spark 为 API 创建不同的许可证。我想限制每月和每小时/每分钟的 API 调用。例如,基本许可证将允许每月 10 000 次 API 调用,但我还想限制同一帐户每小时/分钟的 API 调用。这可以用 laravel spark 完成吗?


有:throttle 和 rate_limit,但我可以限制每月以及每小时/分钟的 API 调用总数吗?例如:每月总共 10 000 次 API 调用,每小时/分钟最多 60 次 API 调用?


根据文档,我可以限制每分钟/小时的访问:https ://laravel.com/docs/6.x/routing#rate-limiting


像这样的东西结合了油门和速率限制:


Route::middleware('auth:api', 'throttle:10|rate_limit,1')->group(function () {     

Route::get('/user', function () { // }); 

});

但我的主要问题是如何将每分钟/小时的速率限制与每月限制结合起来?


一只名叫tom的猫
浏览 102回答 1
1回答

鸿蒙传说

从同一文档页面:您也可以将此功能与动态速率限制结合使用。例如,如果您的User模型包含一个rate_limit属性,您可以将属性的名称传递给throttle中间件,以便用于计算经过身份验证的用户的最大请求数因此,鉴于上述情况,您可以在模型上添加一个访问器User,该访问器根据他们当前的订阅计划获取速率限制值:class User extends Authenticatable{&nbsp; &nbsp; public function getRateLimitAttribute()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // Get license if it's a model&nbsp; &nbsp; &nbsp; &nbsp; if ($license === 'basic') {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return 10000;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; // Return some default here&nbsp; &nbsp; }}然后,您可以像这样使用动态速率限制值:Route::middleware('auth:api', 'throttle:rate_limit,1')->group(function () {&nbsp; &nbsp; // Rate-limited routes});至于每月限额,您需要在某处保留一个柜台,并在每个请求时检查。您可以在另一个中间件中记录每个 API 请求:class LogRequest{&nbsp; &nbsp; public function handle($request, Closure $next)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return $next($request);&nbsp; &nbsp; }&nbsp; &nbsp; public function terminate($request, $response)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; LogRequestJob::dispatch($request);&nbsp; &nbsp; }}class LogRequestJob implements ShouldQueue{&nbsp; &nbsp; use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;&nbsp; &nbsp; public function __construct(Request $request)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; $this->request = $request;&nbsp; &nbsp; }&nbsp; &nbsp; public function handle()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // Insert row for user to log request&nbsp; &nbsp; &nbsp; &nbsp; RequestLog::create([&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'user_id' => $this->request->user()->getKey(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'path' => $this->request->path(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Store any other request data you're interested in&nbsp; &nbsp; &nbsp; &nbsp; ]);&nbsp; &nbsp; }}然后,您需要在处理请求之前检查计数,再次使用中间件:use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;class CheckRequestInLimit{&nbsp; &nbsp; public function handle($request, Closure $next)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; $year = Carbon::now()->year;&nbsp; &nbsp; &nbsp; &nbsp; $month = Carbon::now()->month;&nbsp; &nbsp; &nbsp; &nbsp; $count = RequestLog::user($request->user())->year($year)->month($month)->count();&nbsp; &nbsp; &nbsp; &nbsp; $limit = $request->user()->monthly_limit; // another accessor&nbsp; &nbsp; &nbsp; &nbsp; if ($count < $limit) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return $next($request);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; // Count is equal to (or greater than) limit; throw exception&nbsp; &nbsp; &nbsp; &nbsp; $retryAfter = Carbon::today()->addMonth()->startOfMonth();&nbsp; &nbsp; &nbsp; &nbsp; $message = 'You have exceeded your monthly limit';&nbsp; &nbsp; &nbsp; &nbsp; throw new TooManyRequestsHttpException($retryAfter, $message);&nbsp; &nbsp; }}希望这能让您深思!2021 年 11 月 1 日编辑:此答案是针对旧版本的 Laravel 编写的。Laravel 后来引入了速率限制,这将为上述问题提供更简洁的解决方案:RateLimiter::for('api', function (Request $request) {&nbsp; &nbsp; return [&nbsp; &nbsp; &nbsp; &nbsp; Limit::perHour(60)->by($request->user()->getKey()),&nbsp; &nbsp; &nbsp; &nbsp; Limit::perDay(10000, 30)->by($request->user()->getKey()),&nbsp; &nbsp; ];});
打开App,查看更多内容
随时随地看视频慕课网APP