Laravel Middleware a fondo: Autenticación, Rate Limiting y Middleware personalizado
Guía completa sobre middleware en Laravel con ejemplos prácticos: guards de autenticación, limitación de tasa con throttle, creación de middleware personalizado y patrones avanzados para aplicaciones en producción.

El middleware de Laravel actúa como una capa de filtrado entre las solicitudes HTTP entrantes y la lógica de la aplicación. Cada solicitud atraviesa un pipeline de clases middleware antes de llegar a un controlador, y cada respuesta recorre el mismo pipeline en sentido inverso. Comprender este mecanismo resulta esencial para construir aplicaciones Laravel seguras y de alto rendimiento en 2026.
El middleware intercepta las solicitudes HTTP antes de que lleguen a las rutas. Laravel 12 registra todos los middleware en bootstrap/app.php mediante una API fluida. Los middleware integrados gestionan la autenticación, la protección CSRF, el manejo de sesiones y la limitación de tasa de forma nativa.
Cómo funciona el pipeline de middleware en Laravel
El kernel HTTP de Laravel procesa cada solicitud a través de una pila de middleware. Cada middleware recibe la solicitud, ejecuta su lógica y, o bien la pasa a la siguiente capa mediante $next($request), o bien cortocircuita el pipeline devolviendo una respuesta directamente.
Esta arquitectura sigue el patrón de diseño Chain of Responsibility. Un middleware puede actuar antes de que la solicitud llegue al controlador (por ejemplo, verificaciones de autenticación), después de que se genere la respuesta (por ejemplo, agregando encabezados), o en ambos momentos.
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
}
}Este middleware envuelve la solicitud: registra el tiempo de inicio antes del procesamiento y registra la duración después de que la respuesta regresa. Este patrón antes/después es el núcleo del funcionamiento del middleware.
Middleware de autenticación: protegiendo las rutas
Laravel incluye el alias de middleware auth, mapeado a Illuminate\Auth\Middleware\Authenticate. Al aplicarlo a una ruta, se garantiza que solo los usuarios autenticados puedan acceder a ella. Los usuarios no autenticados reciben una respuesta 401 (API) o son redirigidos a la página de inicio de sesión (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']);
});Autenticación con múltiples guards
Las aplicaciones con varios tipos de usuarios (panel de administración, área de clientes, API) se benefician de la autenticación basada en guards. El middleware auth acepta un parámetro de guard para especificar qué driver de autenticación utilizar.
// 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']);
});El parámetro de guard después de los dos puntos indica a Laravel qué configuración de autenticación verificar. Este enfoque mantiene la lógica de autenticación limpia y separada entre las distintas partes de la aplicación.
El middleware guest es el inverso de auth: solo permite el paso a usuarios no autenticados. Al aplicarlo a las rutas de inicio de sesión y registro, se evita que los usuarios ya autenticados accedan a esas páginas.
Limitación de tasa con el middleware Throttle
La limitación de tasa mediante middleware en Laravel protege las rutas contra abusos usando el middleware integrado throttle. Su forma más simple acepta dos parámetros: el número máximo de solicitudes y la ventana de tiempo en minutos.
// 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 con nombre para control avanzado
Definir rate limiters con nombre en AppServiceProvider ofrece un control granular sobre los límites basados en el contexto del usuario. Este enfoque resulta más flexible que los parámetros throttle en línea.
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);
});
});
}La aplicación de limiters con nombre a las rutas utiliza la sintaxis 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']);El rate limiter escalonado del ejemplo anterior muestra un patrón de producción: los usuarios enterprise obtienen límites más altos, los usuarios autenticados reciben límites moderados, y las solicitudes anónimas se restringen de forma agresiva. El método by() determina la clave de limitación: el identificador de usuario para usuarios autenticados y la dirección IP como alternativa.
¿Listo para aprobar tus entrevistas de Laravel?
Practica con nuestros simuladores interactivos, flashcards y tests técnicos.
Construir middleware personalizado desde cero
La creación de middleware personalizado cubre escenarios que los middleware integrados no manejan. El comando Artisan make:middleware genera una nueva clase con la estructura correcta.
php artisan make:middleware EnsureUserHasRoleMiddleware de control de acceso por roles
Un patrón común de middleware personalizado aplica autorización basada en roles a nivel de ruta, aceptando nombres de roles como parámetros.
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);
}
}El parámetro variádico ...$roles permite pasar múltiples roles separados por comas. El registro y la utilización se presentan así:
->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 transformación de solicitudes
Un middleware puede modificar la solicitud antes de que llegue al controlador. A continuación, un middleware para API JSON que impone encabezados de tipo de contenido y limpia las entradas de tipo string:
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);
}
}Este middleware gestiona dos responsabilidades: valida el tipo de contenido para solicitudes POST y sanea todas las entradas de texto eliminando espacios en blanco innecesarios.
Registro de middleware en Laravel 12
Laravel 12 centraliza el registro de todos los middleware en bootstrap/app.php. Esta metodología reemplazó el antiguo archivo app/Http/Kernel.php que existía antes de 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();El array priority cobra importancia cuando se asignan múltiples middleware a la misma ruta. Laravel los ordena según esta lista, garantizando que la sesión se inicie antes de ejecutar la autenticación, y que la autenticación se complete antes de las verificaciones de roles.
Los middleware se ejecutan en el orden de registro. Para los middleware de ruta, el array priority sobrescribe el orden predeterminado. Siempre se debe colocar la autenticación antes de la autorización para evitar verificar roles en solicitudes no autenticadas.
Middleware terminable para tareas post-respuesta
El middleware terminable ejecuta lógica después de que la respuesta ha sido enviada al cliente. Resulta especialmente útil para tareas de registro, analítica o limpieza que no deben bloquear al usuario.
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(),
]);
}
}El método terminate recibe tanto la solicitud original como la respuesta final. Se recomienda registrar el middleware como singleton en AppServiceProvider para asegurar que la misma instancia maneje tanto handle() como terminate().
Patrones de middleware para producción
Varios patrones de middleware aparecen de manera recurrente en las aplicaciones Laravel en producción.
Bypass del modo mantenimiento: permitir que las IPs internas accedan a la aplicación durante el mantenimiento:
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);
}
}Encabezados de seguridad: agregar HSTS, política de seguridad del contenido y otros encabezados a cada respuesta:
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;
}
}Estos patrones ilustran las dos posiciones principales del middleware: antes de la solicitud (el bypass de mantenimiento verifica la IP y potencialmente bloquea el acceso) y después de la respuesta (los encabezados de seguridad modifican la respuesta saliente).
¿Listo para aprobar tus entrevistas de Laravel?
Practica con nuestros simuladores interactivos, flashcards y tests técnicos.
Conclusión
- El middleware de Laravel opera como un pipeline: cada clase procesa la solicitud, actúa sobre ella y la pasa al siguiente nivel o cortocircuita con una respuesta
- El middleware
authprotege las rutas con autenticación basada en guards, soportando múltiples tipos de usuarios mediante la sintaxisauth:guard - La limitación de tasa a través del middleware
throttley las definiciones con nombreRateLimiter::for()habilitan un control de acceso escalonado según el contexto del usuario - Los middleware personalizados gestionan responsabilidades transversales como verificaciones de roles, saneamiento de solicitudes y encabezados de seguridad sin sobrecargar los controladores
- Todo el registro de middleware en Laravel 12 ocurre en
bootstrap/app.phpmediante una API fluida, conprioritypara controlar el orden de ejecución - El middleware terminable ejecuta tareas post-respuesta (analítica, registro) sin impactar la latencia percibida por el usuario
- Los parámetros de middleware mediante la sintaxis
:parammantienen las definiciones de ruta expresivas y las clases middleware reutilizables en diferentes contextos
¡Empieza a practicar!
Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.
Etiquetas
Compartir
Artículos relacionados

Preguntas de Entrevista sobre Laravel y PHP: Las 25 Principales en 2026
Las 25 preguntas mas comunes en entrevistas sobre Laravel y PHP. Eloquent ORM, middleware, artisan, colas, tests y arquitectura con respuestas detalladas y ejemplos de codigo.

Laravel 11: Construir una Aplicacion Completa desde Cero
Guia completa para construir una aplicacion con Laravel 11: autenticacion, API REST, Eloquent ORM y despliegue a produccion. Tutorial practico para desarrolladores principiantes e intermedios.

Symfony 7: API Platform y Mejores Practicas
Guia completa de API Platform 4 con Symfony 7. Recursos, grupos de serializacion, state processors, filtros, seguridad y pruebas automatizadas para APIs REST profesionales.