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.

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.
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:
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.
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.
// 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.
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.
// 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.
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:
Route::middleware('throttle:api')->group(function () {
Route::apiResource('/posts', PostController::class);
});
// routes/web.php
Route::middleware('throttle:login')
->post('/login', [AuthController::class, 'login']);Pronto a superare i tuoi colloqui su Laravel?
Pratica con i nostri simulatori interattivi, flashcards e test tecnici.
Creare middleware personalizzati
Laravel consente di generare la struttura base di un nuovo middleware tramite il comando Artisan dedicato:
php artisan make:middleware EnsureUserHasRoleQuesto 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:
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:
->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:
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.
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.
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.
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:
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:
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.
Pronto a superare i tuoi colloqui su Laravel?
Pratica con i nostri simulatori interattivi, flashcards e test tecnici.
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
authprotegge le rotte da accessi non autenticati, con supporto per guard multiple (web, sanctum, personalizzate) e la possibilita di combinarlo con il middlewareverifiedper la verifica dell'email - Il rate limiting tramite
throttlee la facadeRateLimiterproteggono 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:middlewaree possono accettare parametri variabili, consentendo implementazioni flessibili come la verifica dei ruoli e la sanificazione degli input - La registrazione in
bootstrap/app.phpcentralizza 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
Inizia a praticare!
Metti alla prova le tue conoscenze con i nostri simulatori di colloquio e test tecnici.
Tag
Condividi
Articoli correlati

Domande per colloqui Laravel e PHP: le Top 25 nel 2026
Le 25 domande piu frequenti nei colloqui Laravel e PHP. Eloquent ORM, middleware, Artisan, code, test e architettura con risposte dettagliate ed esempi di codice.

Laravel 11: Creare un'applicazione completa da zero
Guida completa a Laravel 11: installazione, modelli Eloquent, autenticazione con Breeze, controller, rotte, autorizzazione con le policy, REST API con Sanctum, test con Pest e deploy in produzione.

Symfony 7: API Platform e Best Practices
Guida completa ad API Platform 4 con Symfony 7: State Processors, State Providers, gruppi di serializzazione, filtri, sicurezza e test automatizzati per API REST professionali.