Restrict users from accessing website based on IP addresses from database

Here, we will block users from specific IP addresses from accessing our application. Let’s assume you already have a working Laravel application. If not create a fresh Laravel application and configure the database.

To restrict users based on the IP address we need to check every request coming from the user against the database. We can simply do this by creating custom middleware.

Before starting we need to create a table to store blocked IP addresses and we will use this model to store blocked IPs and check against the requested IP address.

Create a Blocked IP Address Model and Migration

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

php artisan make:model BlockedIp -mfs

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

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

<?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 the below command into a terminal :

php artisan migrate

Let’s migrate this migration file and create a table in our database.

The above command will also generate a model factory and seeder. Let’s modify it to seed some dummy data into it.

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

class BlockedIpFactory extends Factory
{
    public function definition()
    {
        return [
            'ip' => $this->faker->ipv4(),
        ];
    }
}
<?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 addresses while you run the below command.

Currently, BlockIpSeeder is configured to create 10 dummy records however you can modify it as per your preference. Let’s seed some IPs by running the below command into a terminal:

php artisan db:seed --class=BlockedIpSeeder

Create Restrict IP Middleware

In Laravel, middleware is a filtering mechanism that filters requests and responses. To create middleware open the terminal and enter the following command :

php artisan make:middleware RestrictIpAddress

Once our middleware is created we can apply logic for IP Restriction into this middleware. Open and modify middleware to check request’s IP is blocked or not and if it’s blocked then show the user-specific table:

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

In the above middleware, it will check current request IP address exists in our database or not. If it exists in our database then it will abort the operation and show a message as a result.

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 and make the 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

php artisan serve

open below URL into your browser :

http://127.0.0.1:8000

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