为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

PHP
一只名叫tom的猫 2022-07-16 16:54:54
我想使用 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 () { // }); });但我的主要问题是如何将每分钟/小时的速率限制与每月限制结合起来?
查看完整描述

1 回答

?
鸿蒙传说

TA贡献1865条经验 获得超7个赞

从同一文档页面:


您也可以将此功能与动态速率限制结合使用。例如,如果您的User模型包含一个rate_limit属性,您可以将属性的名称传递给throttle中间件,以便用于计算经过身份验证的用户的最大请求数


因此,鉴于上述情况,您可以在模型上添加一个访问器User,该访问器根据他们当前的订阅计划获取速率限制值:


class User extends Authenticatable

{

    public function getRateLimitAttribute()

    {

        // Get license if it's a model


        if ($license === 'basic') {

            return 10000;

        }


        // Return some default here

    }

}

然后,您可以像这样使用动态速率限制值:


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

    // Rate-limited routes

});

至于每月限额,您需要在某处保留一个柜台,并在每个请求时检查。您可以在另一个中间件中记录每个 API 请求:


class LogRequest

{

    public function handle($request, Closure $next)

    {

        return $next($request);

    }


    public function terminate($request, $response)

    {

        LogRequestJob::dispatch($request);

    }

}

class LogRequestJob implements ShouldQueue

{

    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;


    public function __construct(Request $request)

    {

        $this->request = $request;

    }


    public function handle()

    {

        // Insert row for user to log request

        RequestLog::create([

            'user_id' => $this->request->user()->getKey(),

            'path' => $this->request->path(),

            // Store any other request data you're interested in

        ]);

    }

}

然后,您需要在处理请求之前检查计数,再次使用中间件:


use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;


class CheckRequestInLimit

{

    public function handle($request, Closure $next)

    {

        $year = Carbon::now()->year;

        $month = Carbon::now()->month;

        $count = RequestLog::user($request->user())->year($year)->month($month)->count();

        $limit = $request->user()->monthly_limit; // another accessor


        if ($count < $limit) {

            return $next($request);

        }


        // Count is equal to (or greater than) limit; throw exception

        $retryAfter = Carbon::today()->addMonth()->startOfMonth();

        $message = 'You have exceeded your monthly limit';


        throw new TooManyRequestsHttpException($retryAfter, $message);

    }

}

希望这能让您深思!


2021 年 11 月 1 日编辑:此答案是针对旧版本的 Laravel 编写的。Laravel 后来引入了速率限制,这将为上述问题提供更简洁的解决方案:


RateLimiter::for('api', function (Request $request) {

    return [

        Limit::perHour(60)->by($request->user()->getKey()),

        Limit::perDay(10000, 30)->by($request->user()->getKey()),

    ];

});


查看完整回答
反对 回复 2022-07-16
  • 1 回答
  • 0 关注
  • 101 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信