节流时间问题
Issue in Throttle time
我在Laravel 5.5
trait ThrottlesLogins
中添加了如下方法
protected function TotalRegisterAttemptsLeft($request) {
$this->incrementAttempts($request);
return $this->limiter()->retriesLeft($this->resolveRequestSignature($request), 3);
}
路线
Route::post('apiregister',
array(
'uses' => 'API\Register\RegisterAPIController@Registration',
'as' => 'apiRegister',
'middleware' => 'throttle:3,1'
)
);
此方法在 5.4 中完美运行,让我解释一下问题。
我有一条注册 POST 路线,最多尝试 3 次。在使用完所有 3 次尝试后,用户将不得不等待 60 秒。
但问题是,假设我在 3 次尝试中花费了 12 秒。尝试 3 次后,它说,请在 48 秒后重试。它应该改为说,请在 60 秒后重试。
如果您需要更多详细信息,请告诉我。
这是 ThrottleRequests 中间件中的错误或预期行为。您可以在更改现有集成测试时轻松重现:
public function test_lock_opens_immediately_after_decay()
{
Carbon::setTestNow(null);
Route::get('/', function () {
return 'yes';
})->middleware(ThrottleRequests::class.':2,1');
$response = $this->withoutExceptionHandling()->get('/');
$this->assertEquals('yes', $response->getContent());
$this->assertEquals(2, $response->headers->get('X-RateLimit-Limit'));
$this->assertEquals(1, $response->headers->get('X-RateLimit-Remaining'));
Carbon::setTestNow(
Carbon::now()->addSeconds(10)
);
$response = $this->withoutExceptionHandling()->get('/');
$this->assertEquals('yes', $response->getContent());
$this->assertEquals(2, $response->headers->get('X-RateLimit-Limit'));
$this->assertEquals(0, $response->headers->get('X-RateLimit-Remaining'));
Carbon::setTestNow(
Carbon::now()->addSeconds(58)
);
try {
$this->withoutExceptionHandling()->get('/');
} catch (Throwable $e) {
$this->assertEquals(429, $e->getStatusCode());
$this->assertEquals(2, $e->getHeaders()['X-RateLimit-Limit']);
$this->assertEquals(0, $e->getHeaders()['X-RateLimit-Remaining']);
$this->assertEquals(2, $e->getHeaders()['Retry-After']);
$this->assertEquals(Carbon::now()->addSeconds(2)->getTimestamp(), $e->getHeaders()['X-RateLimit-Reset']);
}
}
我刚刚添加
Carbon::setTestNow(
Carbon::now()->addSeconds(10)
);
在第一个和第二个请求之间。这将导致 phpunit 的以下输出:
./vendor/bin/phpunit tests/Integration/Http/ThrottleRequestsTest.php
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.
Runtime: PHP 7.2.1
Configuration: /Volumes/Workspace/Projects/laravel/phpunit.xml.dist
F 1 / 1 (100%)
Time: 172 ms, Memory: 10.00MB
There was 1 failure:
1) Illuminate\Tests\Integration\Http\ThrottleRequestsTest::test_lock_opens_immediately_after_decay
Failed asserting that -8 matches expected 2.
/Volumes/Workspace/Projects/laravel/tests/Integration/Http/ThrottleRequestsTest.php:54
我已经用失败的测试创建了一个 PR 〜一旦确认这不是预期的行为,有人可以开始修复它:〜
https://github.com/laravel/framework/pull/22725/files
编辑:如 PR 中所述,这是预期的行为。中间件专为 API 速率限制而设计,您希望在特定时间范围内允许 x 数量的请求通过。为了限制密码尝试,您必须关闭底层的 RateLimiter。
至于为什么以前有效,我不能告诉你。
我在Laravel 5.5
trait ThrottlesLogins
中添加了如下方法
protected function TotalRegisterAttemptsLeft($request) {
$this->incrementAttempts($request);
return $this->limiter()->retriesLeft($this->resolveRequestSignature($request), 3);
}
路线
Route::post('apiregister',
array(
'uses' => 'API\Register\RegisterAPIController@Registration',
'as' => 'apiRegister',
'middleware' => 'throttle:3,1'
)
);
此方法在 5.4 中完美运行,让我解释一下问题。
我有一条注册 POST 路线,最多尝试 3 次。在使用完所有 3 次尝试后,用户将不得不等待 60 秒。
但问题是,假设我在 3 次尝试中花费了 12 秒。尝试 3 次后,它说,请在 48 秒后重试。它应该改为说,请在 60 秒后重试。
如果您需要更多详细信息,请告诉我。
这是 ThrottleRequests 中间件中的错误或预期行为。您可以在更改现有集成测试时轻松重现:
public function test_lock_opens_immediately_after_decay()
{
Carbon::setTestNow(null);
Route::get('/', function () {
return 'yes';
})->middleware(ThrottleRequests::class.':2,1');
$response = $this->withoutExceptionHandling()->get('/');
$this->assertEquals('yes', $response->getContent());
$this->assertEquals(2, $response->headers->get('X-RateLimit-Limit'));
$this->assertEquals(1, $response->headers->get('X-RateLimit-Remaining'));
Carbon::setTestNow(
Carbon::now()->addSeconds(10)
);
$response = $this->withoutExceptionHandling()->get('/');
$this->assertEquals('yes', $response->getContent());
$this->assertEquals(2, $response->headers->get('X-RateLimit-Limit'));
$this->assertEquals(0, $response->headers->get('X-RateLimit-Remaining'));
Carbon::setTestNow(
Carbon::now()->addSeconds(58)
);
try {
$this->withoutExceptionHandling()->get('/');
} catch (Throwable $e) {
$this->assertEquals(429, $e->getStatusCode());
$this->assertEquals(2, $e->getHeaders()['X-RateLimit-Limit']);
$this->assertEquals(0, $e->getHeaders()['X-RateLimit-Remaining']);
$this->assertEquals(2, $e->getHeaders()['Retry-After']);
$this->assertEquals(Carbon::now()->addSeconds(2)->getTimestamp(), $e->getHeaders()['X-RateLimit-Reset']);
}
}
我刚刚添加
Carbon::setTestNow(
Carbon::now()->addSeconds(10)
);
在第一个和第二个请求之间。这将导致 phpunit 的以下输出:
./vendor/bin/phpunit tests/Integration/Http/ThrottleRequestsTest.php
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.
Runtime: PHP 7.2.1
Configuration: /Volumes/Workspace/Projects/laravel/phpunit.xml.dist
F 1 / 1 (100%)
Time: 172 ms, Memory: 10.00MB
There was 1 failure:
1) Illuminate\Tests\Integration\Http\ThrottleRequestsTest::test_lock_opens_immediately_after_decay
Failed asserting that -8 matches expected 2.
/Volumes/Workspace/Projects/laravel/tests/Integration/Http/ThrottleRequestsTest.php:54
我已经用失败的测试创建了一个 PR 〜一旦确认这不是预期的行为,有人可以开始修复它:〜
https://github.com/laravel/framework/pull/22725/files
编辑:如 PR 中所述,这是预期的行为。中间件专为 API 速率限制而设计,您希望在特定时间范围内允许 x 数量的请求通过。为了限制密码尝试,您必须关闭底层的 RateLimiter。
至于为什么以前有效,我不能告诉你。