Laravel Middleware im Detail: Authentifizierung, Rate Limiting und eigene Middleware
Umfassender Leitfaden zu Laravel Middleware mit praktischen Beispielen zu Authentifizierung, Rate Limiting, eigener Middleware-Erstellung und fortgeschrittenen Produktionsmustern.

Middleware bildet das Fundament jeder robusten Laravel-Anwendung. Sie steht als unsichtbare Filterschicht zwischen eingehenden HTTP-Requests und der Anwendungslogik, prueft Zugriffsrechte, begrenzt die Anfragehaeufigkeit und transformiert Daten -- noch bevor ein Controller eine einzige Zeile Code ausfuehrt. Ob Authentifizierung, Rate Limiting oder massgeschneiderte Prueflogik: Wer Laravel produktionsreif einsetzen will, muss die Middleware-Pipeline im Detail verstehen. Dieser Artikel zeigt anhand konkreter Codebeispiele, wie die Middleware-Pipeline funktioniert, welche eingebauten Middleware-Klassen Laravel mitbringt und wie eigene Middleware fuer spezifische Anforderungen erstellt wird.
Middleware entkoppelt wiederkehrende Querschnittsbelange wie Authentifizierung, Logging und Eingabevalidierung von der eigentlichen Geschaeftslogik. Statt Sicherheitspruefungen in jedem Controller zu wiederholen, werden sie zentral in der Middleware definiert und automatisch auf alle relevanten Routen angewendet. Das Ergebnis: schlanke Controller, konsistente Sicherheitsmechanismen und eine Codebasis, die sich einfach warten laesst.
So funktioniert die Middleware-Pipeline
Die Middleware-Pipeline in Laravel laesst sich am besten als eine Reihe konzentrischer Schichten vorstellen. Jeder HTTP-Request durchlaeuft diese Schichten von aussen nach innen, bis er den Controller erreicht. Die Response durchlaeuft anschliessend dieselben Schichten in umgekehrter Reihenfolge. Dieses Prinzip wird besonders deutlich, wenn man eine Middleware betrachtet, die sowohl vor als auch nach der Controller-Verarbeitung Code ausfuehrt.
Das folgende Beispiel misst die Verarbeitungszeit eines Requests. Der Code vor dem Aufruf von $next($request) wird ausgefuehrt, bevor der Request den Controller erreicht. Der Code danach wird ausgefuehrt, nachdem die Response erzeugt wurde -- ein klassisches Beispiel fuer die Zwiebelschalen-Architektur der Pipeline.
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response;
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
}
}Der Schluessel liegt in $next($request): Dieser Aufruf uebergibt den Request an die naechste Middleware in der Kette. Alles vor diesem Aufruf ist Before-Middleware-Logik, alles danach ist After-Middleware-Logik. Wird $next() nie aufgerufen -- beispielsweise weil eine Authentifizierungspruefung fehlschlaegt -- gelangt der Request gar nicht erst zum Controller.
Authentication Middleware
Die Authentifizierung ist der haeufigste Anwendungsfall fuer Middleware in Laravel. Die eingebaute auth-Middleware stellt sicher, dass nur angemeldete Benutzer auf geschuetzte Routen zugreifen koennen. Nicht authentifizierte Benutzer werden automatisch zur Login-Seite umgeleitet oder erhalten eine 401-Response bei API-Requests.
Routen lassen sich einzeln oder in Gruppen schuetzen. Die Gruppierung ist dabei die bevorzugte Methode, da sie die Routendefinitionen uebersichtlich haelt und sicherstellt, dass keine Route versehentlich ungeschuetzt bleibt.
use App\Http\Controllers\DashboardController;
use App\Http\Controllers\ProfileController;
// 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
Laravel unterstuetzt mehrere Authentication Guards, die parallel eingesetzt werden koennen. Ein Guard definiert, wie Benutzer authentifiziert werden -- ob ueber Sessions, API-Tokens oder benutzerdefinierte Mechanismen. Durch Angabe des Guard-Namens nach dem Doppelpunkt laesst sich steuern, welcher Authentifizierungsmechanismus fuer eine bestimmte Routengruppe verwendet wird.
// 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']);
});Diese Trennung ermoeglicht es, API-Routen mit Sanctum-Tokens und Admin-Routen mit einem separaten Guard abzusichern. Jeder Guard kann eigene Benutzermodelle, Provider und Treiber verwenden, was eine flexible Architektur fuer komplexe Anwendungen schafft.
Neben der auth-Middleware existiert die guest-Middleware, die das umgekehrte Verhalten implementiert: Sie laesst nur nicht-authentifizierte Benutzer durch. Typische Anwendungsfaelle sind Login- und Registrierungsseiten, die authentifizierte Benutzer automatisch zum Dashboard weiterleiten sollen. Die Verwendung erfolgt identisch: Route::middleware('guest')->get('/login', ...).
Rate Limiting mit Throttle
Rate Limiting schuetzt Anwendungen vor Missbrauch, Brute-Force-Angriffen und unbeabsichtigter Ueberlastung. Die throttle-Middleware in Laravel begrenzt die Anzahl der Requests, die ein Client innerhalb eines definierten Zeitfensters senden darf. Wird das Limit ueberschritten, antwortet Laravel automatisch mit dem HTTP-Statuscode 429 (Too Many Requests).
Die einfachste Form der Konfiguration erfolgt direkt in der Routendefinition. Der erste Parameter gibt die maximale Anzahl der Requests an, der zweite das Zeitfenster in Minuten.
// 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']);
});Diese grundlegende Konfiguration reicht fuer einfache Anwendungsfaelle aus. Fuer differenziertere Anforderungen -- etwa unterschiedliche Limits fuer verschiedene Benutzergruppen -- bietet Laravel benannte Rate Limiters an.
Benannte Rate Limiters
Benannte Rate Limiters werden in einem Service Provider definiert und ermoeglichen dynamische, kontextabhaengige Konfigurationen. Das folgende Beispiel zeigt ein gestaffeltes System: Enterprise-Kunden erhalten grosszuegigere Limits als regulaere Benutzer, waehrend anonyme Zugriffe am staerksten eingeschraenkt werden.
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Http\Request;
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 benannten Limiter werden anschliessend ueber ihren Namen in der Routendefinition referenziert, anstatt die numerischen Werte direkt anzugeben.
Route::middleware('throttle:api')->group(function () {
Route::apiResource('/posts', PostController::class);
});
// routes/web.php
Route::middleware('throttle:login')
->post('/login', [AuthController::class, 'login']);Der Vorteil dieses Ansatzes liegt in der zentralen Konfiguration: Werden die Limits angepasst, aendert sich automatisch das Verhalten aller Routen, die den entsprechenden Limiter verwenden. Die by()-Methode steuert dabei, wie Requests gruppiert werden -- ob nach Benutzer-ID, IP-Adresse oder einer beliebigen Kombination.
Bereit für deine Laravel-Interviews?
Übe mit unseren interaktiven Simulatoren, Flashcards und technischen Tests.
Eigene Middleware erstellen
Wenn die eingebauten Middleware-Klassen nicht ausreichen, lassen sich mit einem einzigen Artisan-Befehl neue Middleware-Klassen generieren.
php artisan make:middleware EnsureUserHasRoleDieser Befehl erstellt eine Klasse im Verzeichnis app/Http/Middleware/ mit einer vorbereiteten handle-Methode. Anschliessend kann die gewuenschte Logik implementiert werden.
Rollenbasierte Zugriffskontrolle
Ein typischer Anwendungsfall fuer Custom Middleware ist die rollenbasierte Autorisierung. Die folgende Middleware prueft, ob der authentifizierte Benutzer eine der erforderlichen Rollen besitzt. Durch den Spread-Operator (...$roles) unterstuetzt sie eine variable Anzahl von Rollen als Parameter.
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
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);
}
}Die Registrierung erfolgt als Alias in bootstrap/app.php, sodass die Middleware in Routendefinitionen ueber einen kurzen, sprechenden Namen verwendet werden kann. Parameter werden nach dem Doppelpunkt uebergeben, mehrere durch Komma getrennt.
->withMiddleware(function (Middleware $middleware) {
$middleware->alias([
'role' => \App\Http\Middleware\EnsureUserHasRole::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-Sanitierung fuer APIs
Ein weiterer gaengiger Anwendungsfall ist die Validierung und Bereinigung eingehender API-Requests. Die folgende Middleware stellt sicher, dass POST-Requests den korrekten Content-Type verwenden und bereinigt alle String-Eingaben durch Entfernung ueberfluessiger Leerzeichen.
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
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 wird idealerweise am Anfang der API-Middleware-Gruppe eingefuegt, sodass alle nachfolgenden Middleware-Klassen und Controller bereits bereinigte Daten erhalten.
Middleware-Registrierung in Laravel 12
Seit Laravel 11 hat sich die Middleware-Konfiguration grundlegend veraendert. Statt des frueheren App\Http\Kernel erfolgt die gesamte Registrierung in bootstrap/app.php. Dort lassen sich globale Middleware, Gruppen-Middleware, Aliase und die Ausfuehrungsprioritaet zentral definieren.
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withMiddleware(function (Middleware $middleware) {
// Global middleware (runs on every request)
$middleware->append(
\App\Http\Middleware\LogRequestTime::class
);
// Add to the 'web' middleware group
$middleware->web(append: [
\App\Http\Middleware\TrackPageViews::class,
]);
// Add to the 'api' middleware group
$middleware->api(prepend: [
\App\Http\Middleware\ApiRequestSanitizer::class,
]);
// Register aliases for route-level use
$middleware->alias([
'role' => \App\Http\Middleware\EnsureUserHasRole::class,
'subscribed' => \App\Http\Middleware\EnsureUserIsSubscribed::class,
]);
// Control execution order
$middleware->priority([
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\Auth\Middleware\Authenticate::class,
\App\Http\Middleware\EnsureUserHasRole::class,
]);
})
->create();Die Methoden append() und prepend() steuern, ob eine Middleware am Ende oder am Anfang einer Gruppe eingefuegt wird. Globale Middleware ($middleware->append(...) ohne Gruppenangabe) wird bei jedem Request ausgefuehrt -- unabhaengig davon, ob es sich um eine Web- oder API-Route handelt.
Die Reihenfolge der Middleware-Ausfuehrung ist entscheidend. Die Session muss gestartet sein, bevor die Authentifizierung geprueft werden kann. Die Authentifizierung muss vor der Autorisierung erfolgen. Rate Limiting sollte vor rechenintensiver Geschaeftslogik greifen. Die priority()-Methode erzwingt diese Reihenfolge global, unabhaengig davon, in welcher Reihenfolge die Middleware auf einer Route definiert wurde.
Terminable Middleware
Nicht alle Aufgaben muessen abgeschlossen sein, bevor die Response an den Client gesendet wird. Terminable Middleware implementiert eine zusaetzliche terminate()-Methode, die erst nach dem vollstaendigen Senden der Response ausgefuehrt wird. Der Client erhaelt die Antwort also schneller, waehrend die Anwendung im Hintergrund weitere Verarbeitung vornimmt.
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpFoundation\Response;
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(),
]);
}
}Typische Anwendungsfaelle fuer Terminable Middleware sind Analytics-Erfassung, Audit-Logging, Cache-Aufwaermung und das Versenden von Benachrichtigungen. Wichtig zu beachten: Laravel erstellt fuer die terminate()-Methode eine neue Instanz der Middleware, sofern die Middleware nicht als Singleton im Container registriert ist. Bei zustandsbehafteter Verarbeitung muss dies beruecksichtigt werden.
Produktionsmuster
In Produktionsumgebungen werden haeufig wiederkehrende Middleware-Muster eingesetzt, die ueber die Standardfaelle hinausgehen. Zwei besonders nuetzliche Beispiele sind die Wartungsmodus-Umgehung und das Setzen von Sicherheits-Headern.
Wartungsmodus-Umgehung
Waehrend des Wartungsmodus sollen Entwickler und Administratoren weiterhin auf die Anwendung zugreifen koennen, um Aenderungen zu ueberpruefen. Die folgende Middleware erlaubt den Zugriff von bestimmten IP-Adressen, waehrend alle anderen Besucher die Wartungsseite sehen.
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);
}
}Sicherheits-Header
HTTP-Sicherheits-Header sind ein wesentlicher Bestandteil jeder Produktionsanwendung. Statt sie in der Webserver-Konfiguration zu setzen, koennen sie direkt in einer Middleware definiert werden -- das erleichtert die Versionierung und sorgt dafuer, dass die Header unabhaengig vom verwendeten Webserver gesetzt werden.
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;
}
}Beide Middleware-Klassen eignen sich hervorragend als globale Middleware, da sie auf jeden Request angewendet werden sollen. Die Sicherheits-Header-Middleware ist dabei ein Beispiel fuer After-Middleware, da sie die Response nach der Controller-Verarbeitung modifiziert.
Bereit für deine Laravel-Interviews?
Übe mit unseren interaktiven Simulatoren, Flashcards und technischen Tests.
Zusammenfassung
Laravel Middleware ist weit mehr als eine einfache Filterschicht. Sie bildet das Rueckgrat der Request-Verarbeitung und ermoeglicht eine saubere Architektur, in der Sicherheits- und Infrastrukturbelange von der Geschaeftslogik getrennt sind. Die wichtigsten Erkenntnisse im Ueberblick:
- Pipeline-Architektur: Jeder Request durchlaeuft eine Kette von Middleware-Klassen. Die Position des Codes relativ zu
$next($request)bestimmt, ob Logik vor oder nach der Controller-Verarbeitung ausgefuehrt wird. - Authentication Middleware: Die
auth-Middleware schuetzt Routen vor unauthentifizierten Zugriffen. Multi-Guard-Konfigurationen ermoeglichen separate Authentifizierungsmechanismen fuer Web, API und Admin-Bereiche. - Rate Limiting: Die
throttle-Middleware und benannte Rate Limiters bieten flexible Konfigurationsmoeglichkeiten von einfachen Begrenzungen bis hin zu gestaffelten, rollenbasierten Systemen. - Custom Middleware: Mit
php artisan make:middlewarelassen sich in Sekunden neue Middleware-Klassen erstellen. Parameter, der Spread-Operator und Aliase ermoeglichen wiederverwendbare, konfigurierbare Middleware. - Registrierung in bootstrap/app.php: Seit Laravel 11 erfolgt die gesamte Middleware-Konfiguration zentral in einer einzigen Datei, einschliesslich globaler Middleware, Gruppen, Aliase und Prioritaeten.
- Terminable Middleware: Die
terminate()-Methode ermoeglicht nicht-blockierende Nachverarbeitung nach dem Senden der Response, ideal fuer Analytics und Audit-Logging. - Produktionsmuster: Wartungsmodus-Umgehung und Sicherheits-Header sind typische Beispiele fuer Middleware, die in jeder produktionsreifen Laravel-Anwendung vorhanden sein sollte.
Fang an zu üben!
Teste dein Wissen mit unseren Interview-Simulatoren und technischen Tests.
Tags
Teilen
Verwandte Artikel

Laravel und PHP Interviewfragen: Die Top 25 in 2026
Die 25 haeufigsten Laravel- und PHP-Interviewfragen. Eloquent ORM, Middleware, Artisan, Queues, Tests und Architektur mit ausfuehrlichen Antworten und Codebeispielen.

Laravel 11: Eine vollständige Anwendung von Grund auf erstellen
Umfassender Leitfaden zu Laravel 11: Installation, Eloquent-Modelle, Authentifizierung mit Breeze, Controller, Routen, Autorisierung, REST-API mit Sanctum, Tests mit Pest und Produktions-Deployment.

Symfony 7: API Platform und Best Practices
Vollstaendiger Leitfaden zu API Platform 4 mit Symfony 7. State Processors, State Providers, Serialisierungsgruppen und erweiterte Validierung fuer professionelle REST-APIs.