# Laravel Middleware od podstaw: Uwierzytelnianie, Rate Limiting i własne middleware > Kompleksowy przewodnik po middleware w Laravel - od uwierzytelniania i rate limitingu po tworzenie własnych klas middleware. Praktyczne przykłady kodu i wzorce produkcyjne. - Published: 2026-04-16 - Updated: 2026-04-16 - Author: SharpSkill - Tags: laravel, middleware, php, authentication, rate-limiting - Reading time: 8 min --- Middleware w Laravel pełni rolę warstwy filtrującej pomiędzy przychodzącymi żądaniami HTTP a logiką aplikacji. Każde żądanie przechodzi przez potok klas middleware zanim dotrze do kontrolera, a każda odpowiedź wraca tą samą drogą. Zrozumienie tego mechanizmu jest niezbędne do budowania bezpiecznych i wydajnych aplikacji Laravel w 2026 roku. > **Middleware w pigułce** > > Middleware przechwytuje żądania HTTP zanim dotrą do tras. Laravel 12 rejestruje wszystkie middleware w pliku `bootstrap/app.php` za pomocą płynnego API. Wbudowane middleware obsługują uwierzytelnianie, ochronę CSRF, zarządzanie sesjami i rate limiting od razu po instalacji. ## Jak działa potok middleware w Laravel Jądro HTTP Laravela przetwarza każde żądanie przez stos middleware. Każde middleware otrzymuje żądanie, wykonuje swoją logikę, a następnie przekazuje żądanie do następnej warstwy za pomocą `$next($request)` lub przerywa potok, zwracając odpowiedź bezpośrednio. Ta architektura wykorzystuje wzorzec Chain of Responsibility. Middleware może działać **przed** dotarciem żądania do kontrolera (np. sprawdzanie uwierzytelniania), **po** wygenerowaniu odpowiedzi (np. dodawanie nagłówków) lub w obu przypadkach jednocześnie. ```php // app/Http/Middleware/LogRequestTime.php 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 } } ``` To middleware opakowuje żądanie: rejestruje czas rozpoczęcia **przed** przetwarzaniem i loguje czas trwania **po** otrzymaniu odpowiedzi. Ten wzorzec przed/po stanowi podstawę działania middleware. ## Middleware uwierzytelniania: Ochrona tras Laravel dostarcza alias middleware `auth`, powiązany z `Illuminate\Auth\Middleware\Authenticate`. Zastosowanie go do trasy zapewnia, że tylko uwierzytelnieni użytkownicy mogą uzyskać do niej dostęp. Nieuwierzytelnieni użytkownicy otrzymują odpowiedź 401 (API) lub zostają przekierowani na stronę logowania (web). ```php // routes/web.php 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']); }); ``` ### Uwierzytelnianie z wieloma guardami Aplikacje z wieloma typami użytkowników (panel administracyjny, strefa klienta, API) korzystają z [uwierzytelniania opartego na guardach](/technologies/laravel/interview-questions/authentication). Middleware `auth` przyjmuje parametr guard określający, który sterownik uwierzytelniania ma zostać użyty. ```php // routes/api.php // 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']); }); ``` Parametr guard po dwukropku informuje Laravel, wobec której konfiguracji uwierzytelniania należy dokonać weryfikacji. Dzięki temu logika uwierzytelniania pozostaje czysta i odseparowana w różnych częściach aplikacji. > **Middleware Guest** > > Middleware `guest` jest odwrotnością `auth` — przepuszcza tylko nieuwierzytelnionych użytkowników. Zastosowanie go do tras logowania i rejestracji uniemożliwia zalogowanym użytkownikom ponowny dostęp do tych stron. ## Rate Limiting z middleware Throttle Rate limiting w Laravel chroni trasy przed nadużyciami za pomocą wbudowanego middleware `throttle`. Najprostsza forma przyjmuje dwa parametry: maksymalną liczbę żądań i okno czasowe w minutach. ```php // routes/api.php // 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']); }); ``` ### Nazwane Rate Limitery dla zaawansowanej kontroli Definiowanie nazwanych rate limiterów w `AppServiceProvider` daje precyzyjną kontrolę nad limitami w zależności od kontekstu użytkownika. To podejście jest bardziej elastyczne niż parametry throttle podawane bezpośrednio w trasie. ```php // app/Providers/AppServiceProvider.php 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); }); }); } ``` Zastosowanie nazwanych limiterów do tras odbywa się za pomocą składni `throttle:nazwa`: ```php // routes/api.php Route::middleware('throttle:api')->group(function () { Route::apiResource('/posts', PostController::class); }); // routes/web.php Route::middleware('throttle:login') ->post('/login', [AuthController::class, 'login']); ``` Powyższy warstwowy rate limiter demonstruje wzorzec produkcyjny: użytkownicy enterprise otrzymują wyższe limity, uwierzytelnieni użytkownicy umiarkowane, a anonimowe żądania są ograniczane agresywnie. Metoda `by()` określa klucz rate limitu — identyfikator użytkownika dla uwierzytelnionych i adres IP jako rozwiązanie awaryjne. ## Tworzenie własnych middleware od podstaw Tworzenie własnych [middleware](/technologies/laravel/interview-questions/middleware) obejmuje scenariusze, których wbudowane middleware nie obsługują. Komenda Artisan `make:middleware` tworzy nową klasę z prawidłową strukturą. ```bash php artisan make:middleware EnsureUserHasRole ``` ### Middleware kontroli dostępu opartej na rolach Częstym wzorcem własnego middleware jest wymuszanie [autoryzacji opartej na rolach](/technologies/laravel/interview-questions/authorization-policies) na poziomie trasy, przyjmujące nazwy ról jako parametry. ```php // app/Http/Middleware/EnsureUserHasRole.php 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); } } ``` Parametr wariadyczny `...$roles` pozwala na przekazywanie wielu ról oddzielonych przecinkami. Rejestracja i użycie wyglądają następująco: ```php // bootstrap/app.php ->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); }); ``` ### Middleware transformacji żądań Middleware może modyfikować żądanie zanim dotrze do kontrolera. Przykład middleware dla API JSON, które wymusza nagłówki content type i przycina dane wejściowe: ```php // app/Http/Middleware/ApiRequestSanitizer.php 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); } } ``` To middleware obsługuje dwa aspekty: waliduje typ zawartości dla żądań POST i sanityzuje wszystkie dane wejściowe typu string, usuwając białe znaki. ## Rejestracja middleware w Laravel 12 Laravel 12 centralizuje całą rejestrację middleware w pliku `bootstrap/app.php`. Zastąpiło to starsze podejście z plikiem `app/Http/Kernel.php`, które istniało przed Laravel 11. ```php // bootstrap/app.php 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(); ``` Tablica `priority` ma znaczenie, gdy wiele middleware jest przypisanych do tej samej trasy. Laravel sortuje je zgodnie z tą listą, zapewniając uruchomienie sesji przed uwierzytelnianiem, a uwierzytelniania przed sprawdzaniem ról. > **Kolejność wykonywania middleware** > > Middleware uruchamia się w kolejności rejestracji. Dla middleware na poziomie trasy tablica `priority` nadpisuje domyślną kolejność. Uwierzytelnianie powinno być zawsze umieszczane przed autoryzacją, aby uniknąć sprawdzania ról na nieuwierzytelnionych żądaniach. ## Terminable middleware dla zadań po odpowiedzi Terminable middleware wykonuje logikę **po** wysłaniu odpowiedzi do klienta. Jest to przydatne do logowania, analityki lub zadań porządkowych, które nie powinny blokować użytkownika. ```php // app/Http/Middleware/CollectAnalytics.php 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(), ]); } } ``` Metoda `terminate` otrzymuje zarówno oryginalne żądanie, jak i ostateczną odpowiedź. Middleware należy zarejestrować jako singleton w `AppServiceProvider`, aby upewnić się, że ta sama instancja obsługuje zarówno `handle()`, jak i `terminate()`. ## Praktyczne wzorce middleware w produkcji Kilka wzorców middleware pojawia się konsekwentnie w produkcyjnych [aplikacjach Laravel](/blog/laravel/laravel-11-building-complete-application). **Obejście trybu konserwacji** — umożliwia dostęp do aplikacji z wewnętrznych adresów IP podczas konserwacji: ```php // app/Http/Middleware/MaintenanceBypass.php 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); } } ``` **Nagłówki bezpieczeństwa** — dodaje HSTS, politykę bezpieczeństwa treści i inne nagłówki do każdej odpowiedzi: ```php // app/Http/Middleware/SecurityHeaders.php 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; } } ``` Te wzorce demonstrują dwie podstawowe pozycje middleware: **przed** żądaniem (obejście konserwacji sprawdza IP i potencjalnie blokuje) oraz **po** odpowiedzi (nagłówki bezpieczeństwa modyfikują wychodzącą odpowiedź). ## Podsumowanie - Middleware w Laravel działa jako potok: każda klasa przetwarza żądanie, wykonuje na nim operacje i przekazuje je dalej lub przerywa łańcuch, zwracając odpowiedź - Middleware `auth` chroni trasy za pomocą uwierzytelniania opartego na guardach, wspierając wiele typów użytkowników poprzez składnię `auth:guard` - Rate limiting przez middleware `throttle` i nazwane definicje `RateLimiter::for()` umożliwia warstwową kontrolę dostępu na podstawie kontekstu użytkownika - Własne middleware obsługują zagadnienia przekrojowe, takie jak sprawdzanie ról, sanityzacja żądań i nagłówki bezpieczeństwa, bez zaśmiecania kontrolerów - Cała rejestracja middleware w Laravel 12 odbywa się w `bootstrap/app.php` za pomocą płynnego API, z tablicą `priority` kontrolującą kolejność wykonywania - Terminable middleware wykonuje zadania po odpowiedzi (analityka, logowanie) bez wpływu na opóźnienie odczuwane przez użytkownika - Parametry middleware za pomocą składni `:param` utrzymują definicje tras ekspresyjne, a klasy middleware wielokrotnego użytku w różnych kontekstach --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/pl/blog/laravel/laravel-middleware-deep-dive