Restrict user access as per IP address

This Blog's main objective is to build a functionality that can restrict or block user to access website based on particular IP addresses.

Let's assume you already have working Laravel application. If not create fresh Laravel application and configure database.

To restrict user based on IP address we need to check every request coming from user. We can do that by middleware in Laravel.

Create Restrict IP Middleware

In Laravel, middleware is a filtering mechanism that filters request and a response. For creating middleware open terminal and enter following command :

    
php artisan make:middleware RestrictIpAddress
    

This command will create new file at App\Http\Controllers\RestrictIpAddress.php. Precitally we will write all logic for IP Restriction into this file. So make below changes :

    
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class RestrictIpAddress
{
    public $restrictedIp = [
        '127.0.0.1',
        '127.0.0.2',
        '127.0.0.3',
    ];
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        if (in_array($request->ip(), $this->restrictedIp)) {
            abort(403, "You are restricted to access the site.");
            // return response()->json(['message' => "You are not allowed to access this site."]);
        }
        return $next($request);
    }
}
    

Register Middleware in Kernel

In this last step you need to register newly created middleware to your application. For that open App\Http\Kernel.php make following changes :

    
<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    protected $middleware = [
        // \App\Http\Middleware\TrustHosts::class,
        \App\Http\Middleware\TrustProxies::class,
        \Fruitcake\Cors\HandleCors::class,
        \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    ];

    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
            \App\Http\Middleware\RestrictIpAddress::class,// Add this line
        ],

        'api' => [
            // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];

    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    ];
}
    

Testing Our Functionality

Now our functionality to restrict user based on their IP address is completed so you can test it. For testing you have already added 127.0.0.1 to our blocked list. so run application into localhost and it will raise an error.

    
php artisan serve
    

open below URL into your browser :

    
http://127.0.0.1:8000
    

Here, we defined IP address statically into our middleware but you can also use database for that purpose.

Example - 2 : Block User Access Based on IP Address from Database IPs In Laravel

In this example, we will create a database table which will contains all blocked IP addresses.

Create Blocked IP Address Model and Migration

For this example, first of all we need to create model that stores all blocked IP addresses for that enter below command into your terminal :

    
php artisan make:model BlockedIp -mfs
    

In this command, we have passed multiple parameters mfs while creating model which will create migration, factory and seeder. This additional files will used for seeding data into our model.

Let's make changes in all files one by one.

database\migrations\2020_08_29_030437_create_blocked_ips_table.php

    
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateBlockedIpsTable extends Migration
{
    public function up()
    {
        Schema::create('blocked_ips', function (Blueprint $table) {
            $table->id();
            $table->ipAddress('ip'); //add this line
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('blocked_ips');
    }
}
    

Now, we have to migrate our database. Enter below command into terminal :

    
php artisan migrate
    

This command will generate blocked_ips table into our database. let's add some dummy data into our database using factory and seeder.

database\factories\BlockedIpFactory.php

    
<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

class BlockedIpFactory extends Factory
{
    public function definition()
    {
        return [
            'ip' => $this->faker->ipv4(),
        ];
    }
}
    

database\seeder\BlockedIpSeeder.php

    
<?php

namespace Database\Seeders;

use App\Models\BlockedIp; //add
use Illuminate\Database\Seeder;

class BlockedIpSeeder extends Seeder
{
    public function run()
    {
        $blockedIps = BlockedIp::factory()->count(10)->create(); //add
    }
}
    

This alteration will apply logic for creating 10 dummy address while you run below command.

    
php artisan db:seed --class=BlockedIpSeeder
    

Modify Restrict IP Middleware

While checking IP address from database, you need to do some modification into middleware file so it check IP address from database instead of static array.

App\Http\Middleware\RestrictIpAddress.php

    
<?php

namespace App\Http\Middleware;

use App\Models\BlockedIp;
use Closure;
use Illuminate\Http\Request;

class RestrictIpAddress
{
    public function handle(Request $request, Closure $next)
    {
        if (BlockedIp::where('ip', $request->ip())->exists()) {
            abort(403, "You are restricted to access the site.");
        }
        return $next($request);
    }
}
    

Testing Our Functionality

    
php artisan serve
    

open below URL into your browser :

    
http://127.0.0.1:8000
    

Please note : Here, application generated restricted IP addresses are fake so if it doesn't show error on localhost then add your IP address manually to database for testing.


Share your thoughts

Ask anything about this examples