Skip to content

庄朋龙的博客

有志者自有千方万计,无志者只感千难万难。

Menu
  • 首页
  • 生活
  • 创业
  • 编程
  • 运维
  • 视频课程
    • 跨境独立站
    • Shopee跨境电商
    • TEMU跨境电商
  • 资源分享
    • 网站推荐
    • 开源推荐
    • 可商用字体
    • 书籍分享
Menu

如何在 Laravel 中实现请求数速率限制

Posted on 2022年10月8日2022年10月8日 by 庄朋龙

限制每分钟发送到应用程序的请求数通常是必要的,以防止试图使您的服务器饱和或暴力验证表单的攻击。这就是为什么 Laravel 带有速率限制机制的原因,我们将在这里学习使用它。

Laravel 有两种实现速率限制的方法:

  1. 使用速率限制器中间件:在到达控制器之前限制传入的 HTTP 请求
  2. 使用速率限制抽象:在控制器级别与速率限制器进行更精细的交互

在本文中,我们将只看到第一种实现方法,即使用throttle中间件设置一个简单的限速系统。

开始使用

throttle中间件用于保护路由免受过多 HTTP 请求的过度接收,并在达到限制后限制它们。

首先,您应该首先定义应用程序所需的速率限制器配置。为此,请转到方法App\Providers\RouteServiceProvider定义中的类configureRateLimiting()。

<?php

namespace App\Providers;

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\RateLimiter;

class RouteServiceProvider extends ServiceProvider
{
    // ...
    
    public function boot(): void
    {
        $this->configureRateLimiting();
        
        // ...
    }
    
    /**
     * Configure the rate limiters for the application.
     */
    protected function configureRateLimiting(): void
    {
        RateLimiter::for('global', function (Request $request) {
            return Limit::perMinute(1000);
        });
    }
}

在上面的示例中,我们定义了一个称为速率限制器的速率限制器global,它将对其关联的路由的访问限制为每分钟 1000 个请求。

您可以使用所需的名称创建任意数量的配置。例如,我们可以想象有global, downloads,chat来根据路线自定义限制。

定义了速率限制器后,您可以使用throttle中间件将它们应用到要限制速率的路由,如下所示:

<?php

Route::middleware(['throttle:global'])->group(function () {
    Route::get('/products', [ProductController::class, 'index']);
    Route::get('/products/{product}', [ProductController::class, 'show']);
    Route::post('/products', [ProductController::class, 'store']);
});

Route::middleware(['throttle:downloads'])->group(function () {
    Route::get('/reports/{report}/download', [ReportController::class, 'download']);
    Route::get('/albums/{album}/download', [AlbumController::class, 'download']);
});

如您所见,您只需要传递一个字符串,其中包含throttle:您定义的速率限制器的名称。

对于这些路由,如果达到速率限制,应用程序将返回“429 — Too Many Requests”响应,而不是提供预期的响应。

⚠️注意!api如果您的应用程序有一个使用中间件组的 API ,则默认情况下,中间件将应用于您的类属性中throttles:api定义的这些路由。因此,您必须定义一个称为速率限制器或将其从组中删除。$middlewareGroups['api']App\Http\Kernelapi

分段速率限制

到目前为止,正如我们之前示例中所定义的,我们的速率限制器没有区分用户。他们阻止了应用程序每分钟收到的来自所有用户的请求总数。

这不是很有效,因为它可以阻止那些没有试图淹没应用程序的用户。所以最好设置每个用户的请求限制。by为此,您可以在构建速率限制器时使用该方法:

<?php

RateLimiter::for('downloads', function (Request $request) {
    // 速率将用户限制为每分钟 10 个请求
    return Limit::perMinute(10)->by($request->user()->id);
});

因此,每个用户每分钟只能访问关联的路由 10 次,然后才会受到限制。

如果我们想将速率限制应用于不一定需要身份验证的路由怎么办?事实上,$request->user()可能是null这样,使用 IP 地址也是一个好主意。

<?php

RateLimiter::for('global', function (Request $request) {
    return $request->user()
        ? Limit::perMinute(100)->by($request->user()->id)
        : Limit::perMinute(20)->by($request->ip());
});

经过身份验证的用户现在每分钟可以发送 100 个请求,而未经身份验证的用户每分钟只能发送20 个请求(他们的速率与他们的 IP 地址相关联)。

看起来还不错!我们现在有一个有效的配置速率限制器。将throttle中间件与RateLimiter外观一起使用非常棒且令人愉快。

但是,这RateLimiter不仅意味着与throttle中间件一起使用,您还可以在控制器中以更高级的方式使用它。我邀请您查阅文档以了解更多信息。

Category: 编程

全栈开发者×创业偏执狂

相信代码能改变命运,也相信凌晨四点的服务器警报里有真实的人生。

我的创业项目:
SHOPAGG / SmallShop / DigitShops / 文硕阁

© 2025 庄朋龙的博客