PHP Laravel API - How to limit request to a number of trusted hosts?

233
September 19, 2018, at 4:10 PM

I've seen the following method being available in my Laravel Lumen API 5.7

Request::setTrustedHosts($hostPatterns)

I would like to use it in a middleware in order to limit requests to a specific list of clients.

How should I proceed?

Is there any equivalent for the existing $request->isFromTrustedProxy() method which I believe is designated to do a totally different thing?

Answer 1

Assuming you are limiting guests by IP address or something similar, you could build a middleware like this:

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);
        }
    }
}

For Laravel, you would register this middleware in the Http\Kernel.php under the $middlewareGroups array, like this:

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

For Lumen, you can register by identifying the middleware with a short-hand key in the bootstrap/app.php file:

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

Then you would apply it to the routes you want like this:

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

This should do exactly what you want. You can obviously change out the IP address array to anything that you want.

Answer 2

Based on @eResourcesInc answer because I wanted to limit request to certain trusted clients (like some sister servers consuming an API) here's what I came up with:

Created new entry in .env file with my desired trusted client hostnames

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

Then created the TrustedAccess middleware in App\Http\Middleware\TrustedAccess.php

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;
    }
}

For Lumen, I registered the middleware with a short-hand key in the bootstrap/app.php file:

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

Then I applied it to the routes like this:

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

This is it. Please comment if any suggestions!

Rent Charter Buses Company
READ ALSO
How to make dynamic API

How to make dynamic API

I am trying to make a simple API, that will grab data on specific request

106
How to add an element to past days and upcoming days (weekdays only)

How to add an element to past days and upcoming days (weekdays only)

i want to change the color to gray from the past weekdays and to upcoming days change color to blue

131
PHP if isset $_GET any of the parameters if they are present in the POST request to a script

PHP if isset $_GET any of the parameters if they are present in the POST request to a script

I have a strange case where a script should receive the values of 2 parameters every now and thenOne of the parameters is geo and the other one is tids and I have to explode tids to 4 different variables for my use

131
Question marks instead of Cyrillic alphabet [duplicate]

Question marks instead of Cyrillic alphabet [duplicate]

This question already has an answer here:

124