# Laravel Middleware in Dettaglio: Autenticazione, Rate Limiting e Middleware Personalizzati > Guida completa ai middleware di Laravel con esempi pratici su autenticazione, rate limiting con throttle, creazione di middleware personalizzati e pattern avanzati per applicazioni in produzione. - Published: 2026-04-16 - Updated: 2026-04-16 - Author: SharpSkill - Tags: laravel, middleware, autenticazione, rate-limiting, php - Reading time: 10 min --- I middleware rappresentano il meccanismo centrale di filtraggio delle richieste HTTP in qualsiasi applicazione Laravel. Ogni richiesta in ingresso attraversa una catena ordinata di middleware prima di raggiungere il controller designato, e la risposta generata percorre la stessa catena in senso inverso prima di essere restituita al client. Autenticazione, rate limiting, logging, sanificazione degli input e aggiunta di header di sicurezza sono tutti compiti che trovano nei middleware la loro collocazione naturale. Padroneggiare il funzionamento della pipeline dei middleware, sapere configurare quelli predefiniti e saper creare middleware personalizzati costituisce una competenza imprescindibile per chi sviluppa applicazioni Laravel destinate alla produzione. > **Perche i middleware sono fondamentali** > > I middleware di Laravel funzionano come strati concentrici attorno al nucleo dell'applicazione, secondo il modello architetturale noto come "onion architecture". Ogni richiesta attraversa questi strati in sequenza, e ciascuno strato puo ispezionare la richiesta, modificarla, bloccarla o lasciarla proseguire. La risposta ripercorre gli stessi strati in ordine inverso. Questo schema consente di isolare le responsabilita trasversali (autenticazione, CORS, logging) dalla logica di business contenuta nei controller. ## Come funziona la pipeline dei middleware Quando un client invia una richiesta HTTP a un'applicazione Laravel, il flusso segue un percorso rigoroso e ben definito. Il web server (Nginx o Apache) riceve la richiesta e la inoltra al file `public/index.php`, che avvia il bootstrap del framework. Il kernel HTTP costruisce la pipeline dei middleware, e la richiesta attraversa prima i middleware globali, poi quelli del gruppo assegnato alla rotta (`web` o `api`), e infine quelli dichiarati direttamente sulla rotta stessa. Solo dopo aver superato tutti questi strati, la richiesta raggiunge il controller. La risposta generata dal controller percorre la pipeline in senso inverso, consentendo ai middleware di tipo "after" di modificare la risposta prima che venga inviata al client. Questo modello bidirezionale rende possibile misurare, ad esempio, il tempo totale di elaborazione di una richiesta. Il seguente middleware illustra in modo chiaro il funzionamento della pipeline, registrando il tempo impiegato per elaborare ogni richiesta: ```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 } } ``` La chiamata `$next($request)` rappresenta il punto cardine: tutto il codice che la precede viene eseguito prima che la richiesta raggiunga il controller (logica "before"), mentre tutto il codice che la segue viene eseguito dopo che la risposta e stata generata (logica "after"). Nel caso di `LogRequestTime`, il timestamp di partenza viene catturato prima, e la durata viene calcolata dopo, ottenendo cosi una misurazione completa del ciclo di vita della richiesta. ## Middleware di autenticazione L'autenticazione rappresenta il caso d'uso piu diffuso e fondamentale dei middleware in Laravel. Il framework include middleware predefiniti che coprono i principali scenari di protezione delle rotte. Il middleware `auth` verifica che l'utente sia autenticato. Se la verifica fallisce, l'utente viene reindirizzato alla pagina di login per le richieste web, oppure riceve una risposta HTTP 401 per le richieste API. La protezione puo essere applicata a rotte singole o a gruppi di rotte. ```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']); }); ``` Il raggruppamento delle rotte con `Route::middleware('auth')->group(...)` evita la ripetizione della dichiarazione del middleware su ogni singola rotta, mantenendo il file di routing leggibile e manutenibile. Il middleware `auth` accetta un parametro opzionale che specifica la guard da utilizzare. Le guard definiscono il meccanismo con cui gli utenti vengono autenticati per ciascuna richiesta. La guard `web` utilizza sessioni e cookie, la guard `sanctum` supporta sia sessioni SPA sia token API, e le guard personalizzate consentono di gestire scenari di autenticazione specifici dell'applicazione. ```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']); }); ``` Laravel Sanctum determina automaticamente la strategia di autenticazione da utilizzare: se la richiesta proviene da un dominio first-party configurato, utilizza l'autenticazione basata su sessione; in caso contrario, verifica la presenza di un token Bearer nell'header Authorization. La guard personalizzata `admin` nell'esempio consente di separare completamente il flusso di autenticazione degli amministratori da quello degli utenti standard. > **Il middleware guest** > > Oltre al middleware `auth`, Laravel fornisce il middleware `guest`, che opera in modo speculare: consente l'accesso solo agli utenti non autenticati. Questo middleware risulta utile per le pagine di login e registrazione, dove un utente gia autenticato dovrebbe essere reindirizzato alla dashboard anziche visualizzare nuovamente il modulo di accesso. ## Rate limiting con throttle Il rate limiting protegge l'applicazione da abusi, attacchi brute force e consumo eccessivo delle risorse. Laravel offre un sistema di rate limiting sofisticato tramite il middleware `throttle` e la facade `RateLimiter`. Nella sua forma piu semplice, il middleware `throttle` accetta due parametri: il numero massimo di richieste consentite e l'intervallo di tempo in minuti. Quando il limite viene superato, Laravel restituisce automaticamente una risposta HTTP 429 (Too Many Requests) con gli header `Retry-After` e `X-RateLimit-Reset`. ```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']); }); ``` L'esempio mostra una pratica comune in produzione: applicare limiti piu permissivi per le operazioni di lettura (60 richieste al minuto) e limiti piu restrittivi per le operazioni di scrittura (10 richieste al minuto), combinando il rate limiting con l'autenticazione Sanctum. Per scenari piu complessi, la facade `RateLimiter` consente di definire limiti dinamici e differenziati. I rate limiter personalizzati vengono registrati nel metodo `boot()` del service provider `AppServiceProvider`. ```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); }); }); } ``` Il limiter `api` implementa un sistema di accesso a livelli: gli utenti con abbonamento enterprise dispongono di 500 richieste al minuto, gli utenti autenticati standard di 100, e gli utenti anonimi di soli 20. Il limiter `login` applica un limite di 5 tentativi al minuto per indirizzo IP, con una risposta JSON personalizzata quando il limite viene superato. Questo approccio protegge efficacemente contro gli attacchi brute force sulle credenziali. I rate limiter personalizzati vengono poi referenziati nelle definizioni delle rotte tramite il loro nome: ```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']); ``` ## Creare middleware personalizzati Laravel consente di generare la struttura base di un nuovo middleware tramite il comando Artisan dedicato: ```bash php artisan make:middleware EnsureUserHasRole ``` Questo comando crea un file nella directory `app/Http/Middleware/` con lo scaffolding del middleware pronto per essere implementato. Un esempio pratico e frequente riguarda la verifica dei ruoli utente. Il middleware seguente accetta uno o piu ruoli come parametri e blocca l'accesso se l'utente non possiede almeno uno dei ruoli specificati: ```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); } } ``` L'operatore variadic `...$roles` consente di passare un numero variabile di parametri separati da virgola nella definizione della rotta. La registrazione e l'utilizzo del middleware avvengono come segue: ```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); }); ``` Un altro pattern ricorrente nella costruzione di API robuste e la sanificazione delle richieste in ingresso. Il middleware seguente rifiuta le richieste POST che non specificano il content type JSON e applica il trimming a tutti gli input di tipo stringa: ```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); } } ``` Questo middleware affronta due problemi comuni nelle API: garantisce che le richieste POST utilizzino il formato JSON corretto (restituendo un errore 415 Unsupported Media Type in caso contrario) e normalizza tutti gli input stringa rimuovendo gli spazi bianchi superflui. Posizionandolo all'inizio della pipeline API, tutte le rotte beneficiano automaticamente di questa sanificazione. ## Registrazione dei middleware in Laravel 12 A partire da Laravel 11, la configurazione dei middleware avviene interamente nel file `bootstrap/app.php` tramite il metodo `withMiddleware()`, che ha sostituito la tradizionale classe `App\Http\Kernel`. Questa nuova architettura centralizza la registrazione di middleware globali, gruppi, alias e priorita in un unico punto. ```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(); ``` Questa configurazione illustra i quattro livelli di registrazione disponibili. Il metodo `append()` aggiunge un middleware alla pipeline globale, eseguito su ogni richiesta. I metodi `web()` e `api()` consentono di aggiungere middleware ai rispettivi gruppi, con la possibilita di scegliere tra `append` (aggiunta in coda) e `prepend` (aggiunta in testa). Il metodo `alias()` registra gli alias utilizzabili nelle definizioni delle rotte. Infine, il metodo `priority()` definisce l'ordine di esecuzione garantito. > **Ordine di esecuzione dei middleware** > > L'ordine in cui i middleware vengono eseguiti ha implicazioni dirette sulla correttezza dell'applicazione. Il middleware di gestione delle sessioni deve essere eseguito prima del middleware di autenticazione, poiche l'autenticazione dipende dalla sessione. Allo stesso modo, il middleware di autenticazione deve precedere quello di autorizzazione per ruoli. La lista di priorita in `bootstrap/app.php` garantisce questo ordine a livello globale, indipendentemente dalla sequenza con cui i middleware vengono dichiarati sulle singole rotte. ## Middleware terminabili I middleware terminabili rappresentano un pattern avanzato che consente di eseguire logica dopo che la risposta e stata inviata al client. Implementando il metodo `terminate()`, il middleware puo effettuare operazioni di logging, raccolta metriche o pulizia senza aggiungere latenza alla risposta percepita dall'utente. ```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(), ]); } } ``` Nel metodo `handle()`, la richiesta viene semplicemente inoltrata al middleware successivo senza alcuna elaborazione aggiuntiva. Tutta la logica e concentrata nel metodo `terminate()`, che viene invocato dal framework dopo che la risposta ha raggiunto il client. L'inserimento nel database della tabella analytics avviene quindi in modo completamente trasparente per l'utente, che non subisce alcun ritardo aggiuntivo. Questo approccio risulta particolarmente efficace quando l'applicazione viene eseguita su Laravel Octane, dove il processo rimane attivo tra le richieste. ## Pattern per la produzione Le applicazioni in produzione richiedono middleware specializzati per gestire scenari operativi che vanno oltre l'autenticazione e il rate limiting. Due pattern particolarmente utili riguardano il bypass della modalita di manutenzione e l'aggiunta di header di sicurezza HTTP. Il middleware di bypass della manutenzione consente a indirizzi IP specifici (tipicamente quelli del team di sviluppo) di continuare ad accedere all'applicazione anche quando questa si trova in modalita di manutenzione: ```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); } } ``` L'aggiunta di header di sicurezza HTTP e un altro compito che si presta perfettamente all'implementazione tramite middleware. Questi header istruiscono il browser del client su come gestire il contenuto della risposta, mitigando categorie comuni di attacchi come clickjacking, MIME sniffing e downgrade delle connessioni HTTPS: ```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; } } ``` L'header `X-Content-Type-Options: nosniff` impedisce al browser di interpretare il tipo di contenuto in modo diverso da quello dichiarato dal server. `X-Frame-Options: SAMEORIGIN` previene il clickjacking impedendo l'inclusione della pagina in iframe di domini esterni. `Referrer-Policy` controlla le informazioni inviate nell'header Referer durante la navigazione. `Strict-Transport-Security` forza l'utilizzo di HTTPS per tutte le connessioni successive per un anno, inclusi i sottodomini. Registrando questo middleware come globale, tutte le risposte dell'applicazione beneficiano automaticamente di questi header di sicurezza. ## Conclusione I middleware di Laravel costituiscono un sistema potente e flessibile per gestire le responsabilita trasversali di un'applicazione web, mantenendo i controller snelli e focalizzati sulla logica di business. - **La pipeline dei middleware** opera secondo il modello a cipolla: ogni richiesta attraversa gli strati in ingresso e la risposta li ripercorre in uscita, consentendo logica sia "before" sia "after" rispetto al controller - **Il middleware `auth`** protegge le rotte da accessi non autenticati, con supporto per guard multiple (web, sanctum, personalizzate) e la possibilita di combinarlo con il middleware `verified` per la verifica dell'email - **Il rate limiting tramite `throttle`** e la facade `RateLimiter` proteggono l'applicazione da abusi, con supporto per limiti differenziati in base al tipo di utente, all'endpoint e al tipo di operazione - **I middleware personalizzati** vengono generati con `php artisan make:middleware` e possono accettare parametri variabili, consentendo implementazioni flessibili come la verifica dei ruoli e la sanificazione degli input - **La registrazione in `bootstrap/app.php`** centralizza la configurazione di middleware globali, gruppi, alias e priorita di esecuzione in un unico punto chiaro e leggibile - **I middleware terminabili** consentono di eseguire operazioni non bloccanti dopo l'invio della risposta, risultando ideali per analytics, audit logging e raccolta metriche - **I pattern di produzione** come il bypass della manutenzione e l'aggiunta di header di sicurezza HTTP dimostrano la versatilita dei middleware nel gestire requisiti operativi concreti --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/it/blog/laravel/laravel-middleware-deep-dive