PHP Laravel API - 如何限制对多个受信任主机的请求?
PHP Laravel API - How to limit request to a number of trusted hosts?
我在 Laravel Lumen API 5.7
中看到了以下方法
Request::setTrustedHosts($hostPatterns)
我想在中间件中使用它,以便将请求限制在特定的客户端列表中。
我应该如何进行?
我认为现有的 $request->isFromTrustedProxy()
方法是否有任何等效方法被指定用于做完全不同的事情?
假设您通过 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 地址数组更改为您想要的任何内容。
基于@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 () {
//
}]);
就是这样。有什么建议请评论!
我在 Laravel Lumen API 5.7
中看到了以下方法Request::setTrustedHosts($hostPatterns)
我想在中间件中使用它,以便将请求限制在特定的客户端列表中。
我应该如何进行?
我认为现有的 $request->isFromTrustedProxy()
方法是否有任何等效方法被指定用于做完全不同的事情?
假设您通过 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 地址数组更改为您想要的任何内容。
基于@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 () {
//
}]);
就是这样。有什么建议请评论!