服务器访问 Laravel API 的节流问题
Throttle issue with server accessing a Laravel API
我有一个正在使用 Laravel 的 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',
],
];
relevant throttle code
/**
* 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.');
}
if ($route = $request->route()) {
return sha1($route->getDomain().'|'.$request->ip());
您可以通过 X_FORWARDED_FOR
header 传递客户端的 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
,以便从此 header.[=16] 获取 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。这也会影响节流。
开箱即用的解决方案,如果你使用的版本>=5.6,就是使用dynamic rate limit。
Dynamic Rate Limiting
You may specify a dynamic request maximum based on an attribute of the authenticated User model. For example, if your User model contains a rate_limit attribute, you may pass the name of the attribute to the throttle middleware so that it is used to calculate the maximum request count:
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'],
我有一个正在使用 Laravel 的 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',
],
];
relevant throttle code
/**
* 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.');
}
if ($route = $request->route()) {
return sha1($route->getDomain().'|'.$request->ip());
您可以通过 X_FORWARDED_FOR
header 传递客户端的 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
,以便从此 header.[=16] 获取 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。这也会影响节流。
开箱即用的解决方案,如果你使用的版本>=5.6,就是使用dynamic rate limit。
Dynamic Rate Limiting
You may specify a dynamic request maximum based on an attribute of the authenticated User model. For example, if your User model contains a rate_limit attribute, you may pass the name of the attribute to the throttle middleware so that it is used to calculate the maximum request count:
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'],