我像这样使用拉拉维尔的内置油门:
//File: Kernal
protected $middlewareGroups = [
'api' => ['throttle:10,3']
];
但是,我想在我的一个控制器中执行某些操作后(例如成功登录后(重置计数。
我可以看到这个中间件使用RateLimiter
并且有一个称为clear
的公共方法。
问题是,如何使用它?因为它取决于中间件ThrottleRequests
key
。
- 要获得
ThrottleRequests
的object
,我需要RateLimiter
的实例 - 要获取
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!