Laravel 5:如何重置内置油门/限速器?



我像这样使用拉拉维尔的内置油门:

//File: Kernal
protected $middlewareGroups = [
'api' => ['throttle:10,3']
];

但是,我想在我的一个控制器中执行某些操作后(例如成功登录后(重置计数。

我可以看到这个中间件使用RateLimiter并且有一个称为clear的公共方法。

问题是,如何使用它?因为它取决于中间件ThrottleRequestskey

  1. 要获得ThrottleRequestsobject,我需要RateLimiter的实例
  2. 要获取RateLimiter的对象,我需要Cache的实例。 . .

总而言之,如何使用它没有尽头。 知道吗?

谢谢

由于您的问题被标记为Laravel v5.5,因此适用于以下内容:

对于登录尝试,具体如下:

您可以在控制器中使用IlluminateFoundationAuthAuthenticatesUsers特征,因此您可以访问clearLoginAttempts方法,该方法使用正确的密钥在RateLimiter实例上调用clear()方法,而无需提供密钥。

实际上,如果您查看IlluminateFoundationAuthThrottlesLogins::clearLoginAttempts()是如何实现的,您会发现一旦控制器使用了AuthenticatesUsers特征,$this->throttleKey($request)就可以检索正确的键。

通常:

您始终可以使用app(IlluminateCacheRateLimiter::class)获取IlluminateCacheRateLimiter实例,而 又包含所有配置的限制器和缓存。问题是不可能从这个角度获取缓存键。因此,您确实必须首先找出密钥的设置位置和方式,以便您可以使用相同的密钥进行重置。

标准ThrottleRequests中间件在handle()方法中设置密钥,但实际密钥将取决于配置限制的位置和方式(例如:它是命名限制器还是仅使用数字参数设置,->by(...)调用它以显式设置密钥等(

如果您只需要找到一个特定限制器的键,也许您可以在handle()方法中设置断点并检查。

您的案例

在您的特定情况下,由于它不是命名限制器,因此handle()方法将调用resolveRequestSignature来获取密钥。我认为您无法从控制器轻松访问中间件实例。您可以做的是检查该方法如何生成密钥,并基本上复制该段代码以复制相同的密钥,但我不建议这样做,因为它是一个肮脏且脆弱的解决方案。 如果检查,您将看到密钥可以复制为如下所示的内容:

if ($user = $request->user()) {
$key = sha1($user->getAuthIdentifier());
}
elseif ($route = $request->route()) {
$key = sha1($route->getDomain().'|'.$request->ip());
}

但是在最近的Laravel版本中,您可以显式设置密钥,这是更干净,更可靠的解决方案:

<小时 />

在拉拉维尔8

现在由于这个问题相当古老,大多数人宁愿使用最新版本的 Laravel(截至 8 年 2021 月 12 日的 v12(,因此对他们来说,文档包括"分段"限制器的方法。 能够根据请求(或会话数据等(为不同的请求应用单独的限制计数器。实际上,by()方法实际上设置了限制器的key。因此,您可以设置一个或多个命名限制器,例如:

RateLimiter::for('my_per_ip_limiter', function (Request $request) {
return Limit::perMinute(100)->by($request->ip());
});

这意味着名为my_per_ip_limiter的限制器将使用 IP 作为密钥,因此在控制器中的任何时候您都可以调用:

app(IlluminateCacheRateLimiter::class)->clear($request->ip());

以重置特定 IP 的限制器。或者获取到目前为止的尝试次数:

$attempts_so_far = app(IlluminateCacheRateLimiter::class)->attempts($request->ip());

实际上,您可以使用请求(或会话或其他变量(的任何变量代替IP。

但是,没有办法(我认为(区分命名的限制器。因此,如果相同的键也用于另一个限制器,则它们的命中数将一起计算*并一起清除。因此,为限制器指定一个像my_per_ip_limiter这样的名称才有用,这样您就可以通过名称将该限制器分配给特定路由,例如:

Route::post( 'login', 'AuthLoginController@login' )
->middleware('throttle:my_per_ip_limiter');

但是,如果您确实需要命名限制器来单独重置,则必须使用唯一键,例如在它前面加上一些东西,例如:

RateLimiter::for('my_other_ip_limiter', function (Request $request) {
return Limit::perMinute(100)->by('other_'.$request->ip());
});

这可以独立于另一个清除:

// reset my_other_ip_limiter, but not my_per_ip_limiter :
app(IlluminateCacheRateLimiter::class)->clear('other_'.$request->ip()); 

*:通过一起计算,我的意思是它们会加起来,所以如果你将其中两个应用于同一个请求,每个请求都会使计数器增加 2!

最新更新