Block Access Based on IP Address From Database In Laravel

In this tutorial, we will Block Access Based on IP Address From Database In Laravel to prevent users from specific IP addresses from accessing your application. Make sure you have a working Laravel application; if not, create a fresh Laravel project and configure the database.

To enforce IP-based restrictions, every request from a user needs to be checked against the database. This can be efficiently handled by creating custom middleware that blocks unauthorized IP addresses.

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.

For a simpler way to control access, check out our blog Restrict Website Access Based on IP Address In Laravel to quickly allow or block visitors based on their IP addresses.