Laravel Middleware en profondeur : Authentification, Rate Limiting et Middleware personnalisé
Exploration complète des middleware Laravel avec des exemples pratiques : gardes d'authentification, limitation de débit avec throttle, création de middleware personnalisé et patterns avancés pour les applications en production.

Les middleware Laravel constituent une couche de filtrage entre les requêtes HTTP entrantes et la logique applicative. Chaque requête transite par un pipeline de classes middleware avant d'atteindre un contrôleur, et chaque réponse effectue le chemin inverse à travers le même pipeline. La maîtrise de ce mécanisme est indispensable pour construire des applications Laravel sécurisées et performantes en 2026.
Les middleware interceptent les requêtes HTTP avant qu'elles n'atteignent les routes. Laravel 12 enregistre tous les middleware dans bootstrap/app.php via une API fluide. Les middleware intégrés gèrent l'authentification, la protection CSRF, la gestion des sessions et la limitation de débit de manière native.
Fonctionnement du pipeline middleware dans Laravel
Le kernel HTTP de Laravel traite chaque requête à travers une pile de middleware. Chaque middleware reçoit la requête, exécute sa logique, puis soit transmet la requête à la couche suivante via $next($request), soit court-circuite le pipeline en retournant directement une réponse.
Cette architecture suit le design pattern Chain of Responsibility. Un middleware peut agir avant que la requête atteigne le contrôleur (par exemple, vérification d'authentification), après la génération de la réponse (par exemple, ajout d'en-têtes), ou les deux à la fois.
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
}
}Ce middleware encapsule la requête : il enregistre le temps de départ avant le traitement et journalise la durée après le retour de la réponse. Ce schéma avant/après est au coeur du fonctionnement des middleware.
Middleware d'authentification : protéger les routes
Laravel fournit l'alias middleware auth, associé à Illuminate\Auth\Middleware\Authenticate. Son application à une route garantit que seuls les utilisateurs authentifiés peuvent y accéder. Les utilisateurs non authentifiés reçoivent une réponse 401 (API) ou sont redirigés vers la page de connexion (web).
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']);
});Authentification multi-guards
Les applications comportant plusieurs types d'utilisateurs (panneau d'administration, espace client, API) tirent parti de l'authentification par guard. Le middleware auth accepte un paramètre de guard pour spécifier quel pilote d'authentification utiliser.
// 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']);
});Le paramètre de guard après les deux-points indique à Laravel quelle configuration d'authentification vérifier. Cette approche permet de séparer proprement la logique d'authentification entre les différentes parties de l'application.
Le middleware guest est l'inverse de auth : il ne laisse passer que les utilisateurs non authentifiés. Son application aux routes de connexion et d'inscription empêche les utilisateurs déjà authentifiés d'accéder à ces pages.
Limitation de débit avec le middleware Throttle
La limitation de débit via les middleware Laravel protège les routes contre les abus grâce au middleware intégré throttle. Sa forme la plus simple accepte deux paramètres : le nombre maximum de requêtes et la fenêtre temporelle en minutes.
// 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']);
});Rate limiters nommés pour un contrôle avancé
La définition de rate limiters nommés dans AppServiceProvider offre un contrôle granulaire sur les limites en fonction du contexte utilisateur. Cette approche est plus flexible que les paramètres throttle en ligne.
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);
});
});
}L'application des limiters nommés aux routes utilise la syntaxe throttle:name :
Route::middleware('throttle:api')->group(function () {
Route::apiResource('/posts', PostController::class);
});
// routes/web.php
Route::middleware('throttle:login')
->post('/login', [AuthController::class, 'login']);Le rate limiter par niveaux ci-dessus illustre un pattern de production : les utilisateurs entreprise obtiennent des limites plus élevées, les utilisateurs authentifiés des limites modérées, et les requêtes anonymes sont limitées de manière agressive. La méthode by() détermine la clé de limitation : l'identifiant utilisateur pour les utilisateurs authentifiés et l'adresse IP en solution de repli.
Prêt à réussir tes entretiens Laravel ?
Entraîne-toi avec nos simulateurs interactifs, fiches express et tests techniques.
Créer un middleware personnalisé de A à Z
La création de middleware personnalisé couvre les scénarios que les middleware intégrés ne gèrent pas. La commande Artisan make:middleware génère une nouvelle classe avec la structure appropriée.
php artisan make:middleware EnsureUserHasRoleMiddleware de contrôle d'accès par rôle
Un pattern courant de middleware personnalisé applique l'autorisation basée sur les rôles au niveau des routes, en acceptant les noms de rôles comme paramètres.
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);
}
}Le paramètre variadique ...$roles permet de passer plusieurs rôles séparés par des virgules. L'enregistrement et l'utilisation se présentent ainsi :
->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 de transformation de requête
Un middleware peut modifier la requête avant qu'elle n'atteigne le contrôleur. Voici un middleware pour API JSON qui impose les en-têtes de type de contenu et nettoie les entrées de type chaîne :
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);
}
}Ce middleware gère deux préoccupations : il valide le type de contenu pour les requêtes POST et assainit toutes les entrées textuelles en supprimant les espaces superflus.
Enregistrement des middleware dans Laravel 12
Laravel 12 centralise l'enregistrement de tous les middleware dans bootstrap/app.php. Cette approche remplace l'ancien fichier app/Http/Kernel.php qui existait avant Laravel 11.
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();Le tableau priority est important lorsque plusieurs middleware sont assignés à la même route. Laravel les trie selon cette liste, garantissant que la session est démarrée avant l'exécution de l'authentification, et que l'authentification est terminée avant les vérifications de rôle.
Les middleware s'exécutent dans l'ordre d'enregistrement. Pour les middleware de route, le tableau priority remplace l'ordre par défaut. Il faut toujours placer l'authentification avant l'autorisation pour éviter de vérifier les rôles sur des requêtes non authentifiées.
Middleware terminable pour les tâches post-réponse
Les middleware terminables exécutent une logique après l'envoi de la réponse au client. Cette fonctionnalité est utile pour la journalisation, l'analytique ou les tâches de nettoyage qui ne doivent pas bloquer l'utilisateur.
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(),
]);
}
}La méthode terminate reçoit à la fois la requête d'origine et la réponse finale. Il est recommandé d'enregistrer ce middleware comme singleton dans AppServiceProvider afin de garantir que la même instance gère à la fois handle() et terminate().
Patterns middleware avancés pour la production
Plusieurs patterns middleware reviennent régulièrement dans les applications Laravel en production.
Contournement du mode maintenance : permettre aux adresses IP internes d'accéder à l'application pendant la maintenance :
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);
}
}En-têtes de sécurité : ajouter HSTS, les politiques de sécurité du contenu et d'autres en-têtes à chaque réponse :
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;
}
}Ces patterns illustrent les deux positions principales des middleware : avant la requête (le contournement de maintenance vérifie l'IP et bloque potentiellement) et après la réponse (les en-têtes de sécurité modifient la réponse sortante).
Prêt à réussir tes entretiens Laravel ?
Entraîne-toi avec nos simulateurs interactifs, fiches express et tests techniques.
Conclusion
- Les middleware Laravel fonctionnent comme un pipeline : chaque classe traite la requête, agit dessus, puis la transmet ou court-circuite avec une réponse
- Le middleware
authprotège les routes avec une authentification par guard, supportant plusieurs types d'utilisateurs via la syntaxeauth:guard - La limitation de débit via le middleware
throttleet les définitions nomméesRateLimiter::for()permettent un contrôle d'accès par niveaux selon le contexte utilisateur - Les middleware personnalisés gèrent les préoccupations transversales comme les vérifications de rôle, l'assainissement des requêtes et les en-têtes de sécurité sans encombrer les contrôleurs
- L'enregistrement de tous les middleware dans Laravel 12 se fait dans
bootstrap/app.phpvia une API fluide, avecprioritypour contrôler l'ordre d'exécution - Les middleware terminables exécutent des tâches post-réponse (analytique, journalisation) sans impacter la latence perçue par l'utilisateur
- Les paramètres middleware via la syntaxe
:parammaintiennent des définitions de route expressives et des classes middleware réutilisables dans différents contextes
Passe à la pratique !
Teste tes connaissances avec nos simulateurs d'entretien et tests techniques.
Tags
Partager
Articles similaires

Eloquent ORM : Patterns et optimisations pour Laravel
Maîtrisez Eloquent ORM avec les patterns avancés et techniques d'optimisation. Eager loading, query scopes, accessors, mutators et performance pour applications Laravel.

Questions d'entretien Laravel et PHP : Top 25 en 2026
Les 25 questions d'entretien Laravel et PHP les plus posées. Eloquent ORM, middleware, artisan, queues, tests et architecture avec réponses détaillées et exemples de code.

Laravel 11 : Créer une application complète de A à Z
Guide complet pour créer une application Laravel 11 avec authentification, API REST, Eloquent ORM et déploiement. Tutorial pratique pour débutants et intermédiaires.