Laravel Middleware im Detail: Authentifizierung, Rate Limiting und eigene Middleware

Laravel Middleware mit praktischen Beispielen zu Authentifizierungs-Guards, Rate Limiting mit Throttle, eigener Middleware-Erstellung, PHP-Attributen in Laravel 13 und fortgeschrittenen Produktionsmustern.

Laravel Middleware-Architektur mit Request-Pipeline, Authentifizierung und Rate Limiting

Laravel Middleware fungiert als Filterschicht zwischen eingehenden HTTP-Requests und der Anwendungslogik. Jeder Request durchlaeuft eine Pipeline aus Middleware-Klassen, bevor er einen Controller erreicht, und jede Response durchlaeuft dieselbe Pipeline auf dem Rueckweg. Das Verstaendnis dieses Mechanismus ist essenziell fuer die Entwicklung sicherer, performanter Laravel-Anwendungen.

Middleware auf einen Blick

Middleware faengt HTTP-Requests ab, bevor sie die Routen erreichen. Laravel registriert alle Middleware in bootstrap/app.php ueber eine Fluent-API. Die eingebaute Middleware kuemmert sich um Authentifizierung, CSRF-Schutz, Session-Management und Rate Limiting.

Funktionsweise der Laravel Middleware-Pipeline

Der Laravel HTTP-Kernel verarbeitet jeden Request durch einen Stack von Middleware. Jede Middleware empfaengt den Request, fuehrt ihre Logik aus und gibt den Request entweder ueber $next($request) an die naechste Schicht weiter oder bricht die Pipeline durch direktes Zurueckgeben einer Response ab.

Diese Architektur folgt dem Chain-of-Responsibility-Pattern. Middleware kann vor dem Controller (z.B. Authentifizierungspruefungen), nach der Response-Generierung (z.B. Hinzufuegen von Headern) oder in beiden Phasen agieren.

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

Diese Middleware umschliesst den Request: Sie erfasst die Startzeit vor der Verarbeitung und protokolliert die Dauer nach der Response. Dieses Before/After-Pattern ist zentral fuer die Funktionsweise von Middleware.

Authentication Middleware: Schutz von Routen

Laravel liefert den auth-Middleware-Alias mit, der auf IlluminateAuthMiddlewareAuthenticate verweist. Die Anwendung auf eine Route stellt sicher, dass nur authentifizierte Benutzer Zugriff haben. Nicht authentifizierte Benutzer erhalten eine 401-Response (API) oder werden zur Login-Seite umgeleitet (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-Authentifizierung

Anwendungen mit mehreren Benutzertypen (Admin-Panel, Kundenbereich, API) profitieren von Guard-basierter Authentifizierung. Die auth-Middleware akzeptiert einen Guard-Parameter, um festzulegen, welcher Authentifizierungstreiber verwendet werden soll.

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

Der Guard-Parameter nach dem Doppelpunkt teilt Laravel mit, gegen welche Authentifizierungskonfiguration geprueft werden soll. Dies haelt die Authentifizierungslogik sauber und separiert ueber verschiedene Anwendungsbereiche.

Guest Middleware

Die guest-Middleware ist das Gegenteil von auth und laesst nur nicht authentifizierte Benutzer durch. Die Anwendung auf Login- und Registrierungsrouten verhindert, dass bereits angemeldete Benutzer diese Seiten aufrufen.

Rate Limiting mit Throttle Middleware

Laravel Middleware Rate Limiting schuetzt Routen vor Missbrauch durch die eingebaute throttle-Middleware. Die einfachste Form akzeptiert zwei Parameter: die maximale Anzahl von Requests und das Zeitfenster 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']);
});

Benannte Rate Limiter fuer erweiterte Kontrolle

Die Definition benannter Rate Limiter im AppServiceProvider ermoeglicht feinkoernige Kontrolle ueber Limits basierend auf dem Benutzerkontext. Dieser Ansatz ist flexibler als Inline-Throttle-Parameter. Die offizielle Rate-Limiting-Dokumentation bietet weitere Optionen.

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

Die Anwendung benannter Limiter auf Routen erfolgt mit der throttle:name-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']);

Der gestaffelte Rate Limiter oben demonstriert ein Produktionsmuster: Enterprise-Benutzer erhalten hoehere Limits, authentifizierte Benutzer moderate Limits, und anonyme Requests werden aggressiv gedrosselt. Die by()-Methode bestimmt den Rate-Limit-Schluessel und verwendet die Benutzer-ID fuer authentifizierte Benutzer und die IP-Adresse als Fallback.

Bereit für deine Laravel-Interviews?

Übe mit unseren interaktiven Simulatoren, Flashcards und technischen Tests.

Eigene Middleware von Grund auf erstellen

Das Erstellen eigener Middleware deckt Szenarien ab, die eingebaute Middleware nicht behandelt. Der make:middleware-Artisan-Befehl erstellt eine neue Klasse mit der korrekten Struktur.

bash
php artisan make:middleware EnsureUserHasRole

Rollenbasierte Zugriffskontrolle mit Middleware

Ein gaengiges Muster fuer eigene Middleware ist die rollenbasierte Autorisierung auf Routenebene, die Rollennamen als Parameter akzeptiert.

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

Der variadische ...$roles-Parameter erlaubt die Uebergabe mehrerer Rollen, durch Komma getrennt. Registrierung und Verwendung sehen so aus:

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-Transformations-Middleware

Middleware kann den Request vor dem Controller modifizieren. Eine JSON-API-Middleware, die Content-Type-Header erzwingt und String-Eingaben trimmt:

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

Diese Middleware behandelt zwei Anliegen: Sie validiert den Content-Type fuer POST-Requests und bereinigt alle String-Eingaben durch Entfernen von Leerzeichen.

Middleware-Registrierung in bootstrap/app.php

Laravel zentralisiert die gesamte Middleware-Registrierung in bootstrap/app.php. Dies ersetzte den aelteren app/Http/Kernel.php-Ansatz, der vor Laravel 11 existierte. Dieselbe Fluent-API funktioniert in Laravel 12 und 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();

Das priority-Array ist wichtig, wenn mehrere Middleware derselben Route zugewiesen sind. Laravel sortiert sie gemaess dieser Liste und stellt sicher, dass die Session gestartet wird, bevor die Authentifizierung laeuft, und die Authentifizierung abgeschlossen ist, bevor Rollenpruefungen erfolgen.

Middleware-Ausfuehrungsreihenfolge

Middleware wird in der Reihenfolge der Registrierung ausgefuehrt. Fuer Routen-Middleware ueberschreibt das priority-Array die Standardreihenfolge. Authentifizierung sollte immer vor Autorisierungs-Middleware platziert werden, um Rollenpruefungen bei nicht authentifizierten Requests zu vermeiden.

PHP-Attribute fuer Middleware in Laravel 13

Laravel 13 fuehrte das #[Middleware]-PHP-Attribut ein, um Middleware direkt auf Controller-Klassen und -Methoden zu deklarieren. Dieser Ansatz haelt die Middleware-Konfiguration zusammen mit dem Code, den sie schuetzt, was Autorisierungsregeln lesbarer und wartbarer macht.

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

Das Klassen-Level #[Middleware('auth')] gilt fuer alle Methoden. Methoden-Level-Attribute werden zusaetzlich angewendet: store() erfordert sowohl auth als auch subscribed. Das #[Authorize]-Attribut integriert sich mit Laravels Policy-System und prueft Berechtigungen vor der Methodenausfuehrung.

Dieser attributbasierte Ansatz ist optional. Routen-Datei-Middleware und bootstrap/app.php-Registrierung werden weiterhin vollstaendig unterstuetzt. Teams, die explizite Routendefinitionen bevorzugen, koennen die Fluent-API weiter verwenden; Teams, die selbstdokumentierende Controller wuenschen, koennen Attribute adoptieren.

Terminable Middleware fuer Post-Response-Aufgaben

Terminable Middleware fuehrt Logik nach dem Senden der Response an den Client aus. Dies ist nuetzlich fuer Logging, Analytics oder Bereinigungsaufgaben, die den Benutzer nicht blockieren sollen.

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(),
        ]);
    }
}

Die terminate-Methode erhaelt sowohl den urspruenglichen Request als auch die finale Response. Die Middleware sollte als Singleton im AppServiceProvider registriert werden, um sicherzustellen, dass dieselbe Instanz sowohl handle() als auch terminate() behandelt.

Praktische Middleware-Muster fuer die Produktion

Mehrere Middleware-Muster erscheinen konsistent in produktiven Laravel-Anwendungen.

Wartungsmodus-Bypass erlaubt internen IPs den Zugriff auf die Anwendung waehrend der Wartung:

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-Header fuegen HSTS, Content Security Policy und andere Header zu jeder Response hinzu:

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

Diese Muster demonstrieren die zwei primaeren Middleware-Positionen: vor dem Request (Wartungsmodus-Bypass prueft die IP und blockiert moeglicherweise) und nach der Response (Security-Header modifizieren die ausgehende Response).

Bereit für deine Laravel-Interviews?

Übe mit unseren interaktiven Simulatoren, Flashcards und technischen Tests.

Quellen

Laravel Middleware-Muster fuer die Interview-Vorbereitung

  • Laravel Middleware arbeitet als Pipeline: Jede Klasse verarbeitet den Request, agiert darauf und gibt ihn weiter oder bricht mit einer Response ab
  • Die auth-Middleware schuetzt Routen mit Guard-basierter Authentifizierung und unterstuetzt mehrere Benutzertypen ueber die auth:guard-Syntax
  • Rate Limiting durch throttle-Middleware und benannte RateLimiter::for()-Definitionen ermoeglicht gestaffelte Zugriffskontrolle basierend auf dem Benutzerkontext
  • Eigene Middleware behandelt Querschnittsbelange wie Rollenpruefungen, Request-Sanitisierung und Security-Header, ohne Controller zu ueberfrachten
  • Die gesamte Middleware-Registrierung erfolgt in bootstrap/app.php ueber eine Fluent-API, wobei priority die Ausfuehrungsreihenfolge steuert
  • Laravel 13s #[Middleware]-Attribut erlaubt die direkte Deklaration von Middleware auf Controllern und haelt Autorisierungsregeln neben den Handlern
  • Terminable Middleware fuehrt Post-Response-Aufgaben (Analytics, Logging) ohne Auswirkungen auf die benutzerwahrnehmbare Latenz aus
  • Middleware-Parameter ueber die :param-Syntax halten Routendefinitionen aussagekraeftig und Middleware-Klassen wiederverwendbar

Fang an zu üben!

Teste dein Wissen mit unseren Interview-Simulatoren und technischen Tests.

Tägliche Challenge

Findest du den Bug in Laravel?

Ein echter Codeausschnitt, ein versteckter Bug, ein Versuch pro Tag. Zum Ausprobieren ohne Konto.

Anthony Fillion-Maillet

Geschrieben von

Anthony Fillion-Maillet

Gründer von SharpSkill

Seit über 10 Jahren Fullstack-Entwickler. Er leitet SharpSkill und verantwortet alles, was hier erscheint.

Aktualisiert am 21. September 2026

Tags

#laravel
#middleware
#authentifizierung
#rate-limiting
#php

Teilen

Verwandte Artikel