Laravel或Laravel-Lumen次数限制中间件throttle

原创
小哥 3年前 (2022-11-02) 阅读数 97 #PHP
文章标签 PHPLaravel

在 Laravel 5.6 中,还引入了频率限制功能。所谓频率限制,指的是在指定时间单个用户对某个路由的访问次数限制,该功能有两个使用场景,一个是在某些需要验证/认证的页面限制用户失败尝试次数,提高系统的安全性,另一个是避免非正常用户(比如爬虫)对路由的过度频繁访问,从而提高系统的可用性,此外,在流量高峰期还可以借助此功能进行有效的限流。

在 Laravel 中该功能通过内置的 throttle 中间件来实现,该中间件接收两个参数,第一个是次数上限,第二个是指定时间段(单位:分钟):

Route::middleware(throttle:60,1)->group(function () {
    Route::get(/user, function () {
        //
    });
});

以上路由的含义是一分钟能只能访问路由分组的内路由(如 /user )60 次,超过此限制会返回 429 状态码并提示请求过于频繁。

如果你觉得这种静态设置频率的方式不够灵活,还可以通过模型属性来动态设置频率,例如,我们可以为上述通过 throttle 中间件进行分组的路由涉及到的模型类定义一个 rate_limit 属性,然后这样来动态定义这个路由:

Route::middleware(throttle:rate_limit,1)->group(function () {
    Route::get(/user, function () {
        // 在 User 模型中设置自定义的 rate_limit 属性值
    });
    Route::get(/post, function () {
        // 在 Post 模型中设置自定义的 rate_limit 属性值
    });
});

这样,我们就可以通过为不同的模型类设置不同的 rate_limit 属性值来达到动态设置频率限制的效果了。

Lumen 使用 throttle 限制接口访问频率:

开始

首先我们要在 appHttpMiddleware 中新建 ThrottleRequests.php 文件。

并且把以下链接中的代码拷贝到这个文件中:

https://github.com/illuminate/routing/blob/master/Middleware/ThrottleRequests.php

接着修改文件中的命名空间:

namespace AppHttpMiddleware;

标记同一用户端请求

因为 Lumen 框架缺失部分功能,我们需要修改 ThrottleRequests.php 中的 resolveRequestSignature 方法:

protected function resolveRequestSignature($request){
    return sha1(
        $request->method() .
        | . $request->server(SERVER_NAME) .
        | . $request->path() .
        | . $request->ip()
    );
}

抛出响应

throttle 超过限制时抛出的是 IlluminateHttpExceptionsThrottleRequestsException ,同样 Lumen 框架缺少这个文件,需要自己定义一下,在 app/Exceptions 中新建 ThrottleException.php ,写入以下代码:

isReport;
    }
}

app/Exceptions/Handler.php 捕获该抛出异常,在 render 方法增加以下判断:

if ($exception instanceof ThrottleException) {
    return response([
        code => $exception->getCode(),
        msg => $exception->getMessage()
    ], 429);
}

修改 ThrottleRequests.php 文件中的 buildException 方法:

protected function buildException($key, $maxAttempts){
    $retryAfter = $this->getTimeUntilNextRetry($key);
    $headers = $this->getHeaders(
        $maxAttempts,
        $this->calculateRemainingAttempts($key, $maxAttempts, $retryAfter),
        $retryAfter
    );
    // 修改了这一行
    return new ThrottleException(Too Many Attempts., 429);
}

需在文件头部中添加这一行: use AppExceptionsThrottleException;

注册中间件

bootstrap/app.php 中注册:

$app->routeMiddleware([
     throttle => AppHttpMiddlewareThrottleRequests::class,
]);

到这里我们就加入成功了,接着在路由中添加中间件即可:

$router->group([middleware => [throttle:10,2]],function() use ($router){

    $router->post(feedback,UserController@addFeedback);

});

其中 throttle:10,2 表示的是2分钟内访问10次。

版权声明

所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除

热门