Laravel Middleware Uitgelicht: Authenticatie, Rate Limiting en Eigen Middleware

Beheers Laravel middleware met praktische voorbeelden over authenticatie-guards, rate limiting met throttle, eigen middleware bouwen, PHP-attributen in Laravel 13 en geavanceerde patronen voor productieapplicaties.

Laravel middleware-architectuur met request-pipeline, authenticatie en rate limiting

Laravel middleware fungeert als filterlaag tussen inkomende HTTP-verzoeken en de applicatielogica. Elk verzoek passeert een pipeline van middleware-klassen voordat het een controller bereikt, en elk antwoord reist terug door dezelfde pipeline. Het begrijpen van dit mechanisme is essentieel voor het bouwen van veilige, performante Laravel-applicaties.

Middleware in het kort

Middleware onderschept HTTP-verzoeken voordat ze routes bereiken. Laravel registreert alle middleware in bootstrap/app.php via een fluent API. Ingebouwde middleware regelt authenticatie, CSRF-bescherming, sessiebeheer en rate limiting standaard.

Hoe de Laravel Middleware Pipeline werkt

De Laravel HTTP-kernel verwerkt elk verzoek door een stack van middleware. Elke middleware ontvangt het verzoek, voert zijn logica uit en geeft het verzoek door aan de volgende laag via $next($request) of onderbreekt de pipeline door direct een antwoord te retourneren.

Deze architectuur volgt het Chain of Responsibility-pattern. Middleware kan voor het verzoek de controller bereikt (bijv. authenticatiecontroles), na het genereren van het antwoord (bijv. headers toevoegen), of in beide fasen actief zijn.

app/Http/Middleware/LogRequestTime.phpphp
namespace AppHttpMiddleware;

use Closure;
use IlluminateHttpRequest;
use IlluminateSupportFacadesLog;
use SymfonyComponentHttpFoundationResponse;

class LogRequestTime
{
    public function handle(Request $request, Closure $next): Response
    {
        $start = microtime(true);          // Capture start time

        $response = $next($request);       // Pass to next middleware

        $duration = microtime(true) - $start;
        Log::info('Request completed', [
            'url'      => $request->url(),
            'method'   => $request->method(),
            'duration' => round($duration * 1000, 2) . 'ms',
        ]);

        return $response;                  // Return response up the stack
    }
}

Deze middleware omhult het verzoek: het registreert de starttijd voor verwerking en logt de duur na het terugkeren van het antwoord. Dit before/after-pattern is centraal in hoe middleware werkt.

Authentication Middleware: Routes Beschermen

Laravel levert de auth-middleware-alias, gekoppeld aan IlluminateAuthMiddlewareAuthenticate. Het toepassen op een route zorgt ervoor dat alleen geauthenticeerde gebruikers toegang hebben. Niet-geauthenticeerde gebruikers ontvangen een 401-antwoord (API) of worden doorgestuurd naar de loginpagina (web).

routes/web.phpphp
use AppHttpControllersDashboardController;
use AppHttpControllersProfileController;

// Single route protection
Route::get('/dashboard', [DashboardController::class, 'index'])
    ->middleware('auth');

// Group protection for multiple routes
Route::middleware('auth')->group(function () {
    Route::get('/profile', [ProfileController::class, 'show']);
    Route::put('/profile', [ProfileController::class, 'update']);
    Route::delete('/profile', [ProfileController::class, 'destroy']);
});

Multi-Guard Authenticatie

Applicaties met meerdere gebruikerstypen (adminpaneel, klantengebied, API) profiteren van guard-gebaseerde authenticatie. De auth-middleware accepteert een guard-parameter om te specificeren welke authenticatiedriver gebruikt moet worden.

routes/api.phpphp
// API routes use the 'sanctum' guard
Route::middleware('auth:sanctum')->group(function () {
    Route::get('/user', fn (Request $request) => $request->user());
    Route::apiResource('/orders', OrderController::class);
});

// routes/web.php
// Admin routes use a custom 'admin' guard
Route::middleware('auth:admin')->prefix('admin')->group(function () {
    Route::get('/dashboard', [AdminController::class, 'index']);
    Route::get('/users', [AdminController::class, 'users']);
});

De guard-parameter na de dubbele punt vertelt Laravel tegen welke authenticatieconfiguratie gevalideerd moet worden. Dit houdt de authenticatielogica overzichtelijk en gescheiden over verschillende delen van de applicatie.

Guest Middleware

De guest-middleware is het omgekeerde van auth: het laat alleen niet-geauthenticeerde gebruikers door. Toepassing op login- en registratieroutes voorkomt dat reeds ingelogde gebruikers deze pagina's bereiken.

Rate Limiting met Throttle Middleware

Laravel middleware rate limiting beschermt routes tegen misbruik met de ingebouwde throttle-middleware. De eenvoudigste vorm accepteert twee parameters: het maximale aantal verzoeken en het tijdvenster in minuten.

routes/api.phpphp
// Allow 60 requests per minute per user
Route::middleware('throttle:60,1')->group(function () {
    Route::get('/posts', [PostController::class, 'index']);
    Route::get('/posts/{post}', [PostController::class, 'show']);
});

// Stricter limit for write operations
Route::middleware(['auth:sanctum', 'throttle:10,1'])->group(function () {
    Route::post('/posts', [PostController::class, 'store']);
    Route::put('/posts/{post}', [PostController::class, 'update']);
});

Benoemde Rate Limiters voor Geavanceerde Controle

Het definieren van benoemde rate limiters in AppServiceProvider geeft gedetailleerde controle over limieten gebaseerd op gebruikerscontext. Deze aanpak is flexibeler dan inline throttle-parameters. Zie de officiele rate limiting-documentatie voor extra opties.

app/Providers/AppServiceProvider.phpphp
use IlluminateCacheRateLimitingLimit;
use IlluminateSupportFacadesRateLimiter;
use IlluminateHttpRequest;

public function boot(): void
{
    // API rate limiter with tiered access
    RateLimiter::for('api', function (Request $request) {
        $user = $request->user();

        if ($user?->hasSubscription('enterprise')) {
            return Limit::perMinute(500)->by($user->id);   // Enterprise: 500/min
        }

        if ($user) {
            return Limit::perMinute(100)->by($user->id);   // Authenticated: 100/min
        }

        return Limit::perMinute(20)->by($request->ip());   // Anonymous: 20/min
    });

    // Login limiter to prevent brute force
    RateLimiter::for('login', function (Request $request) {
        return Limit::perMinute(5)
            ->by($request->ip())                            // Key by IP address
            ->response(function () {                        // Custom exceeded response
                return response()->json([
                    'message' => 'Too many login attempts. Try again in a minute.',
                ], 429);
            });
    });
}

Het toepassen van benoemde limiters op routes gebruikt de throttle:naam-syntax:

routes/api.phpphp
Route::middleware('throttle:api')->group(function () {
    Route::apiResource('/posts', PostController::class);
});

// routes/web.php
Route::middleware('throttle:login')
    ->post('/login', [AuthController::class, 'login']);

De gelaagde rate limiter hierboven demonstreert een productiepatroon: enterprise-gebruikers krijgen hogere limieten, geauthenticeerde gebruikers krijgen gematigde limieten, en anonieme verzoeken worden agressief beperkt. De by()-methode bepaalt de rate limit-sleutel, met gebruikers-ID voor geauthenticeerde gebruikers en IP-adres als fallback.

Klaar om je Laravel gesprekken te halen?

Oefen met onze interactieve simulatoren, flashcards en technische tests.

Eigen Middleware vanaf Scratch Bouwen

Het maken van eigen middleware dekt scenario's die ingebouwde middleware niet afhandelt. Het make:middleware-Artisan-commando genereert een nieuwe klasse met de juiste structuur.

bash
php artisan make:middleware EnsureUserHasRole

Rolgebaseerde Toegangscontrole Middleware

Een veelvoorkomend patroon voor eigen middleware is rolgebaseerde autorisatie op routeniveau, waarbij rolnamen als parameters worden geaccepteerd.

app/Http/Middleware/EnsureUserHasRole.phpphp
namespace AppHttpMiddleware;

use Closure;
use IlluminateHttpRequest;
use SymfonyComponentHttpFoundationResponse;

class EnsureUserHasRole
{
    public function handle(Request $request, Closure $next, string ...$roles): Response
    {
        $user = $request->user();

        if (! $user || ! $user->hasAnyRole($roles)) {
            abort(403, 'Insufficient permissions.');
        }

        return $next($request);
    }
}

De variadische ...$roles-parameter maakt het doorgeven van meerdere rollen mogelijk, gescheiden door komma's. Registratie en gebruik zien er zo uit:

bootstrap/app.phpphp
->withMiddleware(function (Middleware $middleware) {
    $middleware->alias([
        'role' => AppHttpMiddlewareEnsureUserHasRole::class,
    ]);
})

// routes/web.php
Route::middleware('role:admin')->group(function () {
    Route::get('/admin', [AdminController::class, 'index']);
});

// Multiple roles: admin OR editor can access
Route::middleware('role:admin,editor')->group(function () {
    Route::resource('/articles', ArticleController::class);
});

Request Transformatie Middleware

Middleware kan het verzoek wijzigen voordat het de controller bereikt. Een JSON API-middleware die content type-headers afdwingt en string-invoer trimt:

app/Http/Middleware/ApiRequestSanitizer.phpphp
namespace AppHttpMiddleware;

use Closure;
use IlluminateHttpRequest;
use SymfonyComponentHttpFoundationResponse;

class ApiRequestSanitizer
{
    public function handle(Request $request, Closure $next): Response
    {
        // Reject non-JSON requests on API routes
        if (! $request->expectsJson() && $request->isMethod('POST')) {
            return response()->json(
                ['error' => 'Content-Type must be application/json'],
                415
            );
        }

        // Trim all string inputs
        $input = $request->all();
        array_walk_recursive($input, function (&$value) {
            if (is_string($value)) {
                $value = trim($value);
            }
        });
        $request->merge($input);

        return $next($request);
    }
}

Deze middleware handelt twee zaken af: het valideert het content type voor POST-verzoeken en sanitiseert alle string-invoer door witruimte te verwijderen.

Middleware Registratie in bootstrap/app.php

Laravel centraliseert alle middleware-registratie in bootstrap/app.php. Dit verving de oudere app/Http/Kernel.php-aanpak die bestond voor Laravel 11. Dezelfde fluent API werkt in Laravel 12 en 13.

bootstrap/app.phpphp
use IlluminateFoundationApplication;
use IlluminateFoundationConfigurationMiddleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withMiddleware(function (Middleware $middleware) {
        // Global middleware (runs on every request)
        $middleware->append(
            AppHttpMiddlewareLogRequestTime::class
        );

        // Add to the 'web' middleware group
        $middleware->web(append: [
            AppHttpMiddlewareTrackPageViews::class,
        ]);

        // Add to the 'api' middleware group
        $middleware->api(prepend: [
            AppHttpMiddlewareApiRequestSanitizer::class,
        ]);

        // Register aliases for route-level use
        $middleware->alias([
            'role'       => AppHttpMiddlewareEnsureUserHasRole::class,
            'subscribed' => AppHttpMiddlewareEnsureUserIsSubscribed::class,
        ]);

        // Control execution order
        $middleware->priority([
            IlluminateSessionMiddlewareStartSession::class,
            IlluminateAuthMiddlewareAuthenticate::class,
            AppHttpMiddlewareEnsureUserHasRole::class,
        ]);
    })
    ->create();

De priority-array is belangrijk wanneer meerdere middleware aan dezelfde route zijn toegewezen. Laravel sorteert ze volgens deze lijst, zodat de sessie wordt gestart voor authenticatie en authenticatie compleet is voor rolcontroles.

Middleware Uitvoeringsvolgorde

Middleware wordt uitgevoerd in de volgorde van registratie. Voor route-level middleware overschrijft de priority-array de standaardvolgorde. Plaats authenticatie altijd voor autorisatie-middleware om rolcontroles op niet-geauthenticeerde verzoeken te voorkomen.

PHP-Attributen voor Middleware in Laravel 13

Laravel 13 introduceerde het #[Middleware]-PHP-attribuut voor het declareren van middleware direct op controllerklassen en -methoden. Deze aanpak houdt middleware-configuratie samen met de code die het beschermt, waardoor autorisatieregels leesbaarder en onderhoudsvriendelijker worden.

app/Http/Controllers/CommentController.phpphp
namespace AppHttpControllers;

use AppModelsComment;
use AppModelsPost;
use IlluminateRoutingAttributesControllersAuthorize;
use IlluminateRoutingAttributesControllersMiddleware;

#[Middleware('auth')]
class CommentController
{
    #[Middleware('subscribed')]
    #[Authorize('create', [Comment::class, 'post'])]
    public function store(Post $post)
    {
        // Only authenticated, subscribed users who can create comments reach here
    }

    public function index(Post $post)
    {
        // Still requires auth (from class-level attribute)
        return $post->comments;
    }
}

Het klasse-level #[Middleware('auth')] geldt voor alle methoden. Methode-level attributen worden gestapeld: store() vereist zowel auth als subscribed. Het #[Authorize]-attribuut integreert met Laravel's policy-systeem, en controleert rechten voor uitvoering van de methode.

Deze attribuut-gebaseerde aanpak is optioneel. Route-file middleware en bootstrap/app.php-registratie blijven volledig ondersteund. Teams die expliciete routedefinities prefereren kunnen de fluent API blijven gebruiken; teams die zelfdocumenterende controllers willen kunnen attributen adopteren.

Terminable Middleware voor Post-Response Taken

Terminable middleware voert logica uit na het verzenden van het antwoord naar de client. Dit is nuttig voor logging, analytics of opruimtaken die de gebruiker niet moeten blokkeren.

app/Http/Middleware/CollectAnalytics.phpphp
namespace AppHttpMiddleware;

use Closure;
use IlluminateHttpRequest;
use IlluminateSupportFacadesDB;
use SymfonyComponentHttpFoundationResponse;

class CollectAnalytics
{
    public function handle(Request $request, Closure $next): Response
    {
        return $next($request);  // Pass through without delay
    }

    public function terminate(Request $request, Response $response): void
    {
        // Runs after response is sent to client
        DB::table('analytics')->insert([
            'path'        => $request->path(),
            'method'      => $request->method(),
            'status_code' => $response->getStatusCode(),
            'user_id'     => $request->user()?->id,
            'ip'          => $request->ip(),
            'created_at'  => now(),
        ]);
    }
}

De terminate-methode ontvangt zowel het originele verzoek als het uiteindelijke antwoord. Registreer de middleware als singleton in AppServiceProvider om te verzekeren dat dezelfde instantie zowel handle() als terminate() afhandelt.

Praktische Middleware Patronen voor Productie

Verschillende middleware-patronen verschijnen consistent in productie Laravel-applicaties.

Onderhoudsmodus bypass staat interne IP's toe om de applicatie te benaderen tijdens onderhoud:

app/Http/Middleware/MaintenanceBypass.phpphp
class MaintenanceBypass
{
    private array $allowedIps = ['192.168.1.0/24', '10.0.0.1'];

    public function handle(Request $request, Closure $next): Response
    {
        if (app()->isDownForMaintenance()) {
            foreach ($this->allowedIps as $ip) {
                if ($request->ip() === $ip) {
                    return $next($request);
                }
            }
        }

        return $next($request);
    }
}

Security headers voegen HSTS, content security policy en andere headers toe aan elk antwoord:

app/Http/Middleware/SecurityHeaders.phpphp
class SecurityHeaders
{
    public function handle(Request $request, Closure $next): Response
    {
        $response = $next($request);

        $response->headers->set('X-Content-Type-Options', 'nosniff');
        $response->headers->set('X-Frame-Options', 'SAMEORIGIN');
        $response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin');
        $response->headers->set(
            'Strict-Transport-Security',
            'max-age=31536000; includeSubDomains'
        );

        return $response;
    }
}

Deze patronen demonstreren de twee primaire middleware-posities: voor het verzoek (onderhoudsmodus bypass controleert het IP en blokkeert mogelijk) en na het antwoord (security headers wijzigen het uitgaande antwoord).

Klaar om je Laravel gesprekken te halen?

Oefen met onze interactieve simulatoren, flashcards en technische tests.

Bronnen

Laravel Middleware Patronen voor Sollicitatiegesprek Voorbereiding

  • Laravel middleware werkt als een pipeline: elke klasse verwerkt het verzoek, handelt erop en geeft het door of onderbreekt met een antwoord
  • De auth-middleware beschermt routes met guard-gebaseerde authenticatie, met ondersteuning voor meerdere gebruikerstypen via auth:guard-syntax
  • Rate limiting via throttle-middleware en benoemde RateLimiter::for()-definities maakt gelaagde toegangscontrole mogelijk op basis van gebruikerscontext
  • Eigen middleware handelt cross-cutting concerns af zoals rolcontroles, request-sanitisatie en security headers zonder controllers te overladen
  • Alle middleware-registratie gebeurt in bootstrap/app.php via een fluent API, waarbij priority de uitvoeringsvolgorde bepaalt
  • Laravel 13's #[Middleware]-attribuut maakt het declareren van middleware direct op controllers mogelijk, waardoor autorisatieregels naast handlers blijven
  • Terminable middleware voert post-response taken uit (analytics, logging) zonder impact op door gebruikers waargenomen latentie
  • Middleware-parameters via de :param-syntax houden routedefinities expressief en middleware-klassen herbruikbaar in verschillende contexten

Begin met oefenen!

Test je kennis met onze gespreksimulatoren en technische tests.

Dagelijkse challenge

Zie jij de bug in Laravel?

Een echt codefragment, een verborgen bug, één poging per dag. Zonder account uit te proberen.

Anthony Fillion-Maillet

Geschreven door

Anthony Fillion-Maillet

Oprichter van SharpSkill

Al meer dan 10 jaar fullstack-ontwikkelaar. Hij leidt SharpSkill en staat in voor alles wat hier verschijnt.

Bijgewerkt op 21 september 2026

Tags

#laravel
#middleware
#authenticatie
#rate-limiting
#php

Delen

Gerelateerde artikelen