【问题标题】:Throttle issue with server accessing a Laravel API服务器访问 Laravel API 的节流问题
【发布时间】:2019-07-11 20:52:18
【问题描述】:

我有一个使用 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.');
}

【问题讨论】:

    标签: php laravel bandwidth-throttling


    【解决方案1】:

    您可以使用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-&gt;ip() 的每次调用都将使用原始客户端 IP,而不是第二台服务器的 IP。这也会影响节流。

    【讨论】:

      【解决方案2】:

      如果您使用 >= 5.6 的版本,开箱即用的解决方案是使用 dynamic rate limit

      动态速率限制

      您可以根据已验证用户模型的属性指定动态请求最大值。例如,如果您的 User 模型包含 rate_limit 属性,您可以将属性名称传递给油门中间件,以便用于计算最大请求数:

      Route::middleware('auth:api', 'throttle:rate_limit,1')->group(function () {
          Route::get('/user', function () {
              //
          });
      });
      

      The relevant part of the code

      /**
       * 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'],
      

      【讨论】:

      • OP 不清楚,但这需要某种身份验证系统。对于一个开放的 API——比如api.github.com/users/github——这个解决方案是行不通的。
      • 确实,它要求调用者经过身份验证,以便为每个用户提供 custom $maxAttempts,但对于开放 API,仍然可以为非经过身份验证的用户。
      【解决方案3】:
      if ($route = $request->route()) {
          return sha1($route->getDomain().'|'.$request->ip());
      

      【讨论】:

      • 请不要只发布一些代码。还要解释它的作用以及它的工作原理。
      • 对不起,我不明白你的答案,你的代码示例不完整。您能否用更多代码和解释详细说明您的答案。或者,如果您回答错误,您可以随时将其删除。谢谢。
      猜你喜欢
      • 1970-01-01
      • 2021-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多