laravle8 访问限制 throttle 中间件

throttle 中间件介绍

频率限制经常用在 API 中,用于限制独立请求者对特定 API 的请求频率。每个 API 都会选择一个自己的频率限制时间跨度,GitHub 选择的是 1 小时,Laravel 中间件选择的是 1 分钟。
例如:throttle:60,1,即设置频率限制为每分钟 60 次,如果一个 IP 一分钟内超过这个限制,那么服务器就会返回 429 Too Many Attempts. 响应。

自定义 throttle 中间件

大家可以参看这两篇文章
Laravel 访问限制 throttle 中间件
Laravel API throttle 原理分析
在这两篇文章中,讲了如何自定义一个throttle中间件。

在laravel8中使用throttle中间件

我们通常在这里一般会使用throttle中间件来做一个限定条件的速率限定,比如说不在IP白名单中的IP限制一分钟访问多少次。相对于之前来说,laravel8中的throttle中间件,有了更简单的使用方法。
首先我们可以看到在Kernel.php文件中有这样的定义

    /**
     * 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\Session\Middleware\AuthenticateSession::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,
        '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' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    ];

很明显看到其实laravel8中定义的'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,是框架已经定义好的,并且在api中使用的是throttle:api
当然,一般的大家的用法可能就是在这里把throttle:api注释掉,新建一个throttle中间件或者是在路由中可以直接使用throttle:60,1这样的。
那如果是需要做一些复杂的判断,比如说我有很多个IP白名单想要排除掉,不做速率限制,或者是有个VVVIP用户不限制速率的时候怎么办呢?
这时,我们可以在laravel8中找到App\Providers\RouteServiceProvider.php文件,在文件最下面我们可以看到这样的写法

    /**
     * Configure the rate limiters for the application.
     *
     * @return void
     */
    protected function configureRateLimiting()
    {
        RateLimiter::for('api', function (Request $request) {
            return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());
        });
    }

这里定义的api就是上面在Kernel.php文件中所使用的的throttle:api。在这里,我们可以设定自定义的速率限制条件,比如说限制用户IP白名单之外的IP访问限制为每小时60次,白名单每次可以访问1000次

RateLimiter::for('apiHour', function (Request $request) {
            if(!in_array($request->ip(), config('ip.whitelist'))){
                return Limit::perHour(60)->by($request->ip());
            }else{
                return Limit::perHour(1000)->by($request->ip());
            }
        });

当然别忘记在config文件夹中新建ip.php文件

return [
    'whitelist' => [
        '192.168.0.1',
    ],
];

:heart:温馨提示:在使用的时候,用的是api接口路由的话,如果想使用自定义的throttle:apiHour不要忘记把原来Kernel.php中的throttle:api注释掉哟!
最后我们就可以在路由中快乐的使用自定义的速率控制中间件了

Route::group([
    'middleware' => ['throttle:apiHour']
], function ($router) {
   Route::get('user', function (Request $request) {
       return $request->user();
   });
});

异常处理

throttle速率器的异常提示是英文的Too Many Attemps,在laravel8中,我们可以在app/Exceptions/Handler.php文件中重新定义throttle速率器的异常提示。

    public function register()
    {
        ......

        //请求速率问题
        $this->renderable(function (ThrottleRequestsException $e) {
            return response()->json([
                'code' => $e->getCode() ?? 0,
                'message' => "请求过快,请一分钟后再重新尝试!"
            ]);
        });

        //日常错误返回
        ......
    }

注意:throttle速率器的异常返回要放到系统异常返回之前,否则是不会起作用的。

以上就是我总结的laravel8中使用自定义throttle速率器的问题,如有问题,大家可以随时指正,谢谢各位同学观看!
如需转载此文章,请注明引用出处哟:yum:

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!