【问题标题】:PHP Laravel API - How to limit request to a number of trusted hosts?PHP Laravel API - 如何限制对多个受信任主机的请求?
【发布时间】:2018-09-18 12:13:47
【问题描述】:

我在 Laravel Lumen API 5.7 中看到了以下方法

Request::setTrustedHosts($hostPatterns)

我想在中间件中使用它,以便将请求限制在特定的客户端列表中。

我应该如何进行?

现有的$request->isFromTrustedProxy() 方法是否有任何等效项,我认为它被指定做完全不同的事情?

【问题讨论】:

    标签: php laravel lumen


    【解决方案1】:

    假设您通过 IP 地址或类似的方式限制访客,您可以构建这样的中间件:

    namespace App\Http\Middleware;
    
    use Closure;
    
    class LimitAccess {
    
        public function handle($request, Closure $next)
        {
            if(env('APP_ENV')=='production') {
                $ipArray = ['127.0.0.1',...]; //Add trusted IP addresses here
                if (in_array(\Request::ip(), $ipArray)) {
                    return $next($request);
                } else {
                    return response("You are not allowed here!", 503);
                }
            } else {
                return $next($request);
            }
        }
    }
    

    对于 Laravel,您可以在 $middlewareGroups 数组下的 Http\Kernel.php 中注册此中间件,如下所示:

    protected $middlewareGroups = [
        'api' => [
            \App\Http\Middleware\LimitAccess::class
        ]
    ];
    

    对于 Lumen,您可以通过在 bootstrap/app.php 文件中使用简写键识别中间件来注册:

    $app->routeMiddleware([
        'limit' => App\Http\Middleware\LimitAccess::class,
    ]);
    

    然后你可以像这样将它应用到你想要的路线上:

    $router->get('url/you/want/to/limit', ['middleware' => 'limit', function () {
        //
    }]);
    

    这应该完全符合您的要求。您显然可以将 IP 地址数组更改为您想要的任何内容。

    【讨论】:

      【解决方案2】:

      基于@eResourcesInc 的回答,因为我想将请求限制在某些受信任的客户端(例如一些使用 API 的姊妹服务器),这就是我想出的:

      .env 文件中使用我想要的受信任的客户端主机名创建了新条目

      TRUSTED_CLIENTS=specific.example.com|*.whatever.net|8-8-8-8.static.example.org
      

      然后在App\Http\Middleware\TrustedAccess.php中创建了TrustedAccess中间件

      namespace App\Http\Middleware;
      
      use Illuminate\Http\Response;
      use Closure;
      
      class TrustedAccess
      {
          private $trustedClients;
      
          public function __construct()
          {
              $this->trustedClients = [];
              if (env('TRUSTED_CLIENTS')) {
                  $list = explode('|', env('TRUSTED_CLIENTS'));
                  if ($list !== false && !empty($list)) {
                      $this->trustedClients = $list;
                  }
              }
          }
      
          /**
           * Handle an incoming request.
           *
           * @param  \Illuminate\Http\Request  $request
           * @param  \Closure  $next
           * @return mixed
           */
          public function handle($request, Closure $next)
          {
              if(env('APP_ENV')=='production') {
                  $clientHostname = gethostbyaddr($request->getClientIp());
                  $isTrusted = false;
                  foreach ($this->trustedClients as $trustedClientHostname) {
                      if (self::isHostnameMatch($clientHostname, $trustedClientHostname)) {
                          $isTrusted = true;
                          break;
                      }
                  }
                  if ($isTrusted) {
                      return $next($request);
                  } else {
                      return response()->json(['error'=>'Unauthorised'], Response::HTTP_UNAUTHORIZED);
                  }
              } else {
                  return $next($request);
              }
          }
      
          private static function isHostnameMatch($hostname, $trustedHostname)
          {
              if ($trustedHostname == '*' || $hostname == $trustedHostname) {
                  return true;
              }
              // check if wildcard subdomain
              $subdomainDelimiterPosition = strpos($hostname, '.');
              if(strlen($trustedHostname) < 2 || $subdomainDelimiterPosition === false) {
                  return false;
              }
              if (substr($trustedHostname, 0, 2) == '*.') {
                  if (substr($trustedHostname, 1) == substr($hostname, $subdomainDelimiterPosition)) {
                      return true;
                  }
              }
              return false;
          }
      }
      

      对于 Lumen,我在 bootstrap/app.php 文件中使用简写键注册了中间件:

      $app->routeMiddleware([
          'trusted' => App\Http\Middleware\TrustedAccess::class,
      ]);
      

      然后我将它应用到这样的路线:

      $router->get('url/I/want/to/limit', ['middleware' => 'trusted', function () {
          //
      }]);
      

      就是这样。有什么建议欢迎评论!

      【讨论】:

        猜你喜欢
        • 2011-03-09
        • 2020-04-04
        • 2012-11-28
        • 2020-03-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多