# 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. - Published: 2026-04-16 - Updated: 2026-04-16 - Author: SharpSkill - Tags: laravel, middleware, authentication, rate-limiting, php - Reading time: 10 min --- 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 en résumé** > > 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. ```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 } } ``` 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). ```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']); }); ``` ### Authentification multi-guards Les applications comportant plusieurs types d'utilisateurs (panneau d'administration, espace client, API) tirent parti de [l'authentification par guard](/technologies/laravel/interview-questions/authentication). Le middleware `auth` accepte un paramètre de guard pour spécifier quel pilote d'authentification utiliser. ```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']); }); ``` 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. > **Middleware Guest** > > 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. ```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']); }); ``` ### 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. ```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); }); }); } ``` L'application des limiters nommés aux routes utilise la syntaxe `throttle:name` : ```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']); ``` 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. ## Créer un middleware personnalisé de A à Z La création de [middleware](/technologies/laravel/interview-questions/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. ```bash php artisan make:middleware EnsureUserHasRole ``` ### Middleware de contrôle d'accès par rôle Un pattern courant de middleware personnalisé applique [l'autorisation basée sur les rôles](/technologies/laravel/interview-questions/authorization-policies) au niveau des routes, en acceptant les noms de rôles comme paramètres. ```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); } } ``` 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 : ```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 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 : ```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); } } ``` 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. ```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(); ``` 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. > **Ordre d'exécution des middleware** > > 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. ```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(), ]); } } ``` 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](/blog/laravel/laravel-11-building-complete-application) en production. **Contournement du mode maintenance** : permettre aux adresses IP internes d'accéder à l'application pendant la maintenance : ```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); } } ``` **En-têtes de sécurité** : ajouter HSTS, les politiques de sécurité du contenu et d'autres en-têtes à chaque réponse : ```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; } } ``` 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). ## 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 `auth` protège les routes avec une authentification par guard, supportant plusieurs types d'utilisateurs via la syntaxe `auth:guard` - La limitation de débit via le middleware `throttle` et les définitions nommées `RateLimiter::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.php` via une API fluide, avec `priority` pour 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 `:param` maintiennent des définitions de route expressives et des classes middleware réutilisables dans différents contextes --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/fr/blog/laravel/laravel-middleware-deep-dive