【问题标题】:Disable rate limiter in Laravel?在 Laravel 中禁用速率限制器?
【发布时间】:2017-08-20 20:35:25
【问题描述】:

有没有办法在 Laravel 中禁用每条/单个路由的速率限制?

我正在尝试测试一个接收大量请求的端点,但是 Laravel 会随机开始响应 { status: 429, responseText: 'Too Many Attempts.' } 来响应几百个请求,这使得测试非常痛苦。

【问题讨论】:

    标签: php laravel


    【解决方案1】:

    app/Http/Kernel.php Laravel 对所有 api 路由都有一个默认的油门限制。

    protected $middlewareGroups = [
        ...
        'api' => [
            'throttle:60,1',
        ],
    ];
    

    评论或增加它。

    【讨论】:

    • 如果我评论是否意味着没有限制?
    • 正确。注释掉意味着没有限制。
    • 此方法强烈不建议使用,除非您的应用程序逻辑有特定的理由来更改限制。如果您想关闭节流以进行测试,请使用:$this->withoutMiddleware()->get($url, $data);
    • 注释掉似乎并不意味着我最近的测试没有限制
    • 有没有办法在达到限制后重置油门?我将系统日期更改为提前 2 个月进行测试,现在“Retry-After”响应 HTTP 标头表明我必须等待 2 个月才能访问 API 路由。
    【解决方案2】:

    您实际上可以在测试中禁用某个中间件。

    use Illuminate\Routing\Middleware\ThrottleRequests;
    
    class YourTest extends TestCase 
    {
    
        protected function setUp()
        {
            parent::setUp();
            $this->withoutMiddleware(
                ThrottleRequests::class
            );
        }
        ...
    }
    

    【讨论】:

    • 这应该是公认的答案,因为这是测试此类内容的正确方法。全局禁用 Throttle 限制不是一个好习惯。
    • 需要 Laravel 5.5+
    • 很好的答案,但是..关于在哪里以及如何使用此代码的更多信息呢?
    【解决方案3】:

    假设您正在使用 API 路由,那么您可以在 app/Http/Kernel.php 中更改节流阀或完全取消它。如果您需要限制其他路由,可以单独为它们注册中间件。

    (以下示例:油门 - 60 次尝试然后锁定 1 分钟)

    'api' => [
            'throttle:60,1',
            'bindings',
        ],
    

    【讨论】:

      【解决方案4】:

      您可以使用cache:clear 命令清除缓存,包括您的速率限制,如下所示:

      php artisan cache:clear
      

      【讨论】:

        【解决方案5】:

        在 Laravel 5.7 中

        动态速率限制 您可以根据已验证用户模型的属性指定动态请求最大值。例如,如果您的 User 模型包含 rate_limit 属性,您可以将属性名称传递给油门中间件,以便用于计算最大请求数:

        Route::middleware('auth:api', 'throttle:rate_limit,1')->group(function () {
            Route::get('/user', function () {
                //
            });
        });
        

        https://laravel.com/docs/5.7/routing#rate-limiting

        【讨论】:

        • 我在 Laravel 5.4 中尝试过,它确实有效,但由于某种原因,它使用了我输入的一半值。
        【解决方案6】:

        如果您只想为自动化测试禁用,您可以在测试中使用 WithoutMiddleware 特征。

        use Illuminate\Foundation\Testing\WithoutMiddleware;
        
        class YourTest extends TestCase {
            use WithoutMiddleware;
        
            ...
        

        否则,只需从您的 Kernel 文件 (app/Http/Kernel.php) 中删除 'throttle:60,1', 行,您的问题就会得到解决。

        【讨论】:

          【解决方案7】:

          您可以在app/Http/Kernel.php 中添加以下行

              'api' => [
                  'throttle:120,1',
                  'bindings',
                   \App\Library\Cobalt\Http\Middleware\LogMiddleware::class,
              ],
          

          如果问题仍然存在,请尝试使用 artisan 命令 php artisan cache:clear

          【讨论】:

            【解决方案8】:

            在单元测试中增加油门以避免可怕的 429 的非 hacky 方法:

            1. 从内核文件中间件中删除节流阀:60,1。
            2. 使用环境变量将油门中间件重新添加到路由组中:
            $requestsPerMinute = ENV("REQUESTS_PER_MINUTE", 60);
            Route::middleware(["auth:api", "throttle:$requestsPerMinute,1"])->group(function(){
              // your routes
            });
            
            1. 在 phpunit.xml 中定义更高的 REQUESTS_PER_MINUTE 环境变量,以便在限制之前允许测试环境中的更多请求。
            <server name="REQUESTS_PER_MINUTE" value="500"/>
            
            1. (还要在 .env 中定义新的 REQUESTS_PER_MINUTE 变量,即使它会回落到 60)。

            【讨论】:

              【解决方案9】:

              如果您使用的是 Laravel 8.x 或更高版本,您可以通过以下步骤使用 RateLimiter:

              在您的 app/Providers/RouteServiceProvider.php 中找到下面的 configureRateLimiting: 受保护的函数 configureRateLimiting() {

                  RateLimiter::for('api', function (Request $request) {
                      return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());
                  });
              
                  // no limit throttle
                  RateLimiter::for('none', function (Request $request) {
                      return Limit::none();
                  });
              
              }
              

              在你的 app/web.php 添加 'throttle:none:

              Route::group(['middleware' => ['auth', 'throttle:none']], function ($router) {
                  Route::post('test', 'TestController@test');
              });
              

              【讨论】:

              • 不适用于 api 路由
              【解决方案10】:

              就我而言,我只是在 `App\Providers\RouteServiceProvider 中更改了 perMinute() 的默认值。

              protected function configureRateLimiting()
                  {
                      RateLimiter::for('api', function (Request $request) {
                          $perMinute = env('APP_ENV') === 'testing' ? 1000 : 60;
              
                          return Limit::perMinute($perMinute)
                            ->by(optional($request->user())->id ?: $request->ip());
                      });
                  }
              
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2021-07-09
                • 2022-10-13
                • 1970-01-01
                • 2021-04-01
                • 2022-10-14
                • 2022-01-07
                • 1970-01-01
                • 2021-10-13
                相关资源
                最近更新 更多