我有一个使用Laravel的API,该API是从另一个带有Guzzle的Laravel实例中调用的。
第二台服务器的IP地址正在触发API的限制。
我想将用户的域和IP地址从第二台服务器传递到API。我希望不要重新编码Throttle中间件。
我想知道以前是否有人遇到过这种问题,以及是否解决过。
API上的中间件组是这样设置的
/**
* The application's route middleware groups.
*
* @var array
*/
protected $middlewareGroups = [
'api' => [
'throttle:60,1',
\Barryvdh\Cors\HandleCors::class,
'bindings',
],
];
/**
* Resolve request signature.
*
* @param \Illuminate\Http\Request $request
* @return string
*
* @throws \RuntimeException
*/
protected function resolveRequestSignature($request)
{
if ($user = $request->user()) {
return sha1($user->getAuthIdentifier());
}
if ($route = $request->route()) {
return sha1($route->getDomain().'|'.$request->ip());
}
throw new RuntimeException('Unable to generate the request signature. Route unavailable.');
}
答案 0 :(得分:4)
您可以使用X_FORWARDED_FOR
标头传递客户端的IP地址,这样就不会阻止第二台服务器的IP地址。
Route::get('/', function (Request $request) {
$client = new \GuzzleHttp\Client();
$request = $client->request('GET', '/api/example', [
'headers' => ['X_FORWARDED_FOR' => $request->ip()]
]);
$response = $request->getBody();
});
在主服务器上,您需要将第二台服务器作为可信代理(docs)添加到App\Http\Middleware\TrustProxies
,以便从此标头中获取IP。
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array
*/
protected $proxies = [
'192.168.1.1', // <-- set the ip of the second server here
];
//...
}
现在,主服务器上对$request->ip()
的每次调用都将具有原始客户端IP,而不是第二台服务器的IP。这也会影响节流。
答案 1 :(得分:0)
如果使用的版本> = 5.6,则开箱即用的解决方案是使用dynamic rate limit。
动态速率限制
您可以根据已验证的用户模型的属性指定最大动态请求数。例如,如果您的用户模型包含rate_limit属性,则可以将该属性的名称传递给节流中间件,以便用于计算最大请求数:
Route::middleware('auth:api', 'throttle:rate_limit,1')->group(function () { Route::get('/user', function () { // }); });
/**
* Resolve the number of attempts if the user is authenticated or not.
*
* @param \Illuminate\Http\Request $request
* @param int|string $maxAttempts
* @return int
*/
protected function resolveMaxAttempts($request, $maxAttempts)
{
if (Str::contains($maxAttempts, '|')) {
$maxAttempts = explode('|', $maxAttempts, 2)[$request->user() ? 1 : 0];
}
if (! is_numeric($maxAttempts) && $request->user()) {
$maxAttempts = $request->user()->{$maxAttempts};
}
return (int) $maxAttempts;
}
因此,您可以在用户(代表第二台服务器)中添加一个rate_limit
属性,并传递一个更大的数字
如果您不希望对调用方进行身份验证,则可以轻松覆盖resolveMaxAttempts
方法,以根据请求数据动态计算限制(可以使用任何参数,主机,ip等) ):
protected function resolveMaxAttempts($request, $maxAttempts)
{
if (in_array(request->ip(), config('app.bypassThrottleMiddleware')) {
return PHP_INT_MAX;
}
return parent::resolveMaxAttempts($request, $maxAttempts);
}
,然后在您的config/app.php
中添加:
'bypassThrottleMiddleware' => ['0.0.0.0'],
答案 2 :(得分:-1)
在routes / api.php中(Laravel 5.6或更高版本)
Route::middleware('auth:api', 'throttle:rate_limit,1')->group(function () {
Route::get('/user', function (Request $request) {
// $request->user()->getsSomethingAndIsRateLimited();
});
});
答案 3 :(得分:-3)
if ($route = $request->route()) {
return sha1($route->getDomain().'|'.$request->ip());