Laravel
Tutorial Laravel: Middleware y control de solicitudes
Laravel: descubre cómo los middleware filtran y gestionan solicitudes HTTP mejorando eficiencia y seguridad en aplicaciones PHP.
Aprende Laravel GRATIS y certifícateConcepto y uso de middleware
En Laravel, un middleware es una capa intermedia que filtra las solicitudes HTTP entrantes antes de que alcancen los controladores. Actúa como un filtro donde se pueden realizar tareas como la autenticación, la gestión de sesiones o la verificación de permisos, asegurando que solo las solicitudes válidas procedan al siguiente nivel.
Los middlewares funcionan como una serie de tuberías a través de las cuales pasa una solicitud. Cada middleware tiene la capacidad de inspeccionar y modificar la solicitud o la respuesta. Además, pueden detener completamente el procesamiento si detectan alguna anomalía, como una falta de autorización.
Por ejemplo, para proteger una ruta y garantizar que solo usuarios autenticados puedan acceder a ella, se utiliza el middleware 'auth':
Route::get('/perfil', function () {
// Lógica del controlador
})->middleware('auth');
En este caso, el middleware 'auth' comprobará si el usuario está autenticado antes de permitir el acceso a la ruta '/perfil'. Si el usuario no está autenticado, el middleware puede redireccionar a la página de inicio de sesión.
Los middlewares también permiten gestionar otras preocupaciones transversales, como el registro de actividades o la implementación de políticas de seguridad. Al centralizar esta lógica, se evita la duplicación de código en los controladores y se mantiene una arquitectura más limpia y modular.
Es posible asignar múltiples middlewares a una sola ruta, proporcionando un control granular sobre el flujo de las solicitudes:
Route::post('/comentario', function () {
// Lógica para añadir un comentario
})->middleware(['auth', 'verificar-rol']);
Aquí, las solicitudes a '/comentario' pasarán primero por el middleware 'auth' y luego por 'verificar-rol', asegurando que el usuario esté autenticado y tenga el rol adecuado.
Además, los middlewares son fundamentales en el ciclo de vida de una solicitud en Laravel. Desde que la solicitud llega al servidor hasta que se envía una respuesta al cliente, los middlewares permiten intervenir en diferentes puntos, facilitando tareas como la compresión de respuestas, la gestión de cors o la validación de tokens CSRF.
Utilizar middlewares de forma adecuada mejora la mantenibilidad y la escalabilidad de las aplicaciones Laravel, ya que promueven una separación clara de responsabilidades y permiten reutilizar componentes en diferentes partes del sistema.
Middleware globales y de ruta
En Laravel, existen dos tipos principales de middleware: globales y de ruta. Los middleware globales se ejecutan en cada solicitud que entra a la aplicación, mientras que los middleware de ruta se aplican únicamente a rutas específicas.
Los middleware globales se registran en el archivo app/Http/Kernel.php
, dentro de la propiedad $middleware
. Al colocar un middleware en esta lista, garantizamos que se ejecute en todas las solicitudes HTTP, permitiendo manejar tareas como la verificación de cookies, la gestión de sesiones o la aplicación de políticas de seguridad.
Por ejemplo, si deseamos que un middleware llamado VerificarMantenimiento
se ejecute globalmente, lo agregamos de la siguiente manera en Kernel.php
:
protected $middleware = [
// Otros middleware globales
\App\Http\Middleware\VerificarMantenimiento::class,
];
Por otro lado, los middleware de ruta se registran en la propiedad $routeMiddleware
del mismo archivo Kernel.php
. Estos middleware se asignan mediante un alias, lo que facilita su aplicación en rutas específicas. Esto permite un control granular sobre qué solicitudes deben pasar por ciertos middleware.
Por ejemplo, para registrar un middleware de ruta llamado VerificarEdad
con el alias edad
, añadimos en Kernel.php
:
protected $routeMiddleware = [
// Otros middleware de ruta
'edad' => \App\Http\Middleware\VerificarEdad::class,
];
Una vez registrado el middleware de ruta, podemos asignarlo a rutas individuales o grupos de rutas. Para aplicar el middleware edad
a una ruta específica, utilizamos el método middleware
en nuestra definición de rutas:
Route::get('/contenido-restringido', function () {
// Lógica de la ruta
})->middleware('edad');
También es posible asignar múltiples middleware a una ruta o grupo de rutas, proporcionando flexibilidad en cómo gestionamos las solicitudes. Por ejemplo, para aplicar tanto el middleware auth
como edad
:
Route::group(['middleware' => ['auth', 'edad']], function () {
Route::get('/perfil', function () {
// Lógica de la ruta
});
});
Los middleware globales y de ruta permiten estructurar y modularizar la aplicación, asegurando que las preocupaciones transversales sean manejadas de manera eficiente. Mientras que los middleware globales se encargan de tareas comunes a todas las solicitudes, los middleware de ruta proporcionan un enfoque más específico, aplicándose solo donde es necesario.
Es importante recordar que el orden en que se aplican los middleware puede afectar el comportamiento de la aplicación. En el caso de los middleware globales, se ejecutan en el orden en que aparecen en la lista $middleware
, mientras que los middleware de ruta se ejecutan en el orden en que se especifican.
Al utilizar middleware de forma adecuada, podemos mejorar la seguridad, el rendimiento y la mantenibilidad de nuestras aplicaciones Laravel, al separar claramente las responsabilidades y reducir la duplicación de código en los controladores.
Creación de middleware personalizados
En muchas ocasiones, es necesario crear middleware personalizados para manejar lógica específica que no está cubierta por los middlewares predeterminados de Laravel. Estos middlewares nos permiten interceptar y modificar solicitudes en función de criterios particulares, agregando una capa adicional de control a nuestra aplicación.
Para crear un middleware personalizado, Laravel proporciona el comando Artisan adecuado. Utilizando la línea de comandos, ejecutamos:
php artisan make:middleware VerificarEdad
Este comando genera una nueva clase de middleware llamada VerificarEdad
en el directorio app/Http/Middleware
. El archivo generado tendrá una estructura básica que podemos modificar según nuestras necesidades.
Dentro de la clase VerificarEdad
, encontramos el método handle
, que es donde implementamos la lógica de nuestro middleware:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class VerificarEdad
{
/**
* Manejar una solicitud entrante.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
if ($request->edad < 18) {
return redirect('acceso-denegado');
}
return $next($request);
}
}
En este ejemplo, el middleware verifica si la solicitud contiene un parámetro edad
menor que 18. Si es así, redirige al usuario a una ruta llamada acceso-denegado
. De lo contrario, la solicitud continúa hacia el siguiente paso utilizando $next($request)
.
Una vez creado el middleware, debemos registrarlo en la aplicación. Para ello, abrimos el archivo app/Http/Kernel.php
y lo añadimos a la propiedad $routeMiddleware
con un alias:
protected $routeMiddleware = [
// Otros middlewares
'verificar.edad' => \App\Http\Middleware\VerificarEdad::class,
];
Con el middleware registrado, podemos aplicarlo a rutas o grupos de rutas utilizando el alias verificar.edad
:
Route::get('/contenido-adulto', function () {
// Contenido para mayores de edad
})->middleware('verificar.edad');
Ahora, cualquier solicitud a /contenido-adulto
pasará por el middleware VerificarEdad
, asegurando que solo usuarios mayores de 18 años accedan a este contenido.
Es posible que nuestros middlewares necesiten parámetros adicionales. Laravel permite pasar parámetros a los middlewares en la definición de rutas. Por ejemplo, si deseamos que la edad mínima sea variable:
public function handle(Request $request, Closure $next, $edadMinima)
{
if ($request->edad < $edadMinima) {
return redirect('acceso-denegado');
}
return $next($request);
}
Al definir la ruta, pasamos el parámetro adicional al middleware:
Route::get('/contenido-restringido', function () {
// Contenido restringido
})->middleware('verificar.edad:21');
En este caso, el middleware verifica si la edad es menor que 21. Los parámetros facilitados en la definición de la ruta se reciben en el método handle
del middleware.
Además, podemos aplicar múltiples middlewares a una misma ruta:
Route::get('/area-segura', function () {
// Lógica de la ruta
})->middleware(['auth', 'verificar.edad:18']);
Aquí, la ruta /area-segura
requiere que el usuario esté autenticado y además cumpla con el requisito de edad.
Los middlewares personalizados son una herramienta poderosa para encapsular lógica común que necesita ser aplicada a múltiples rutas o controladores. Al crear middlewares específicos, mantenemos nuestro código organizado y promovemos la reutilización de componentes.
Es importante recordar que los middlewares siguen el ciclo de vida de las solicitudes en Laravel, y que pueden modificar tanto la solicitud entrante como la respuesta saliente. Por ejemplo, podemos crear un middleware que añada encabezados HTTP personalizados a las respuestas:
public function handle(Request $request, Closure $next)
{
$response = $next($request);
$response->headers->set('X-Encabezado-Personalizado', 'ValorEncabezado');
return $response;
}
Con este middleware, todas las respuestas tendrán un nuevo encabezado X-Encabezado-Personalizado
, lo que puede ser útil para añadir metadatos o información de depuración.
Otra utilidad de los middlewares personalizados es la manipulación de idiomas o localización. Por ejemplo, podemos crear un middleware que establezca el idioma de la aplicación en función de un parámetro en la solicitud:
public function handle(Request $request, Closure $next)
{
if ($request->has('lang')) {
App::setLocale($request->get('lang'));
}
return $next($request);
}
Al aplicar este middleware, nuestra aplicación puede adaptarse dinámicamente al idioma preferido por el usuario.
La creación de middlewares personalizados nos permite adaptar el comportamiento de nuestra aplicación a necesidades específicas, manteniendo una arquitectura limpia y modular. Al encapsular la lógica transversal en middlewares, facilitamos el mantenimiento y la escalabilidad de nuestro código.
Grupos de middleware y prioridades
Los grupos de middleware en Laravel permiten agrupar varios middleware bajo un solo alias, facilitando su aplicación a rutas o controladores de manera más eficiente. Estos grupos simplifican la gestión de middlewares cuando múltiples rutas requieren las mismas capas de procesamiento.
En el archivo app/Http/Kernel.php
, los grupos de middleware se definen en la propiedad $middlewareGroups
. Laravel proporciona dos grupos predefinidos: web
y api
. Por ejemplo, el grupo web
suele contener middleware esenciales para aplicaciones web tradicionales, como el manejo de sesiones, protección CSRF y encriptación de cookies:
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// Otros middlewares del grupo 'web'
],
'api' => [
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
// Otros middlewares del grupo 'api'
],
];
Para crear un grupo de middleware personalizado, simplemente añadimos una nueva entrada en $middlewareGroups
. Por ejemplo, si deseamos crear un grupo llamado admin
que aplique ciertos middlewares específicos para rutas de administración:
protected $middlewareGroups = [
// Grupos existentes
'admin' => [
'auth',
'verificar.rol:administrador',
\App\Http\Middleware\RegistrarActividad::class,
],
];
En este ejemplo, el grupo admin
incluye el middleware auth
, el middleware personalizado verificar.rol
con el parámetro administrador
, y otro middleware RegistrarActividad
. Al agruparlos, podemos aplicarlos a rutas de administración de forma sencilla.
Para asignar este grupo de middleware a rutas, utilizamos el método middleware
en nuestras definiciones de rutas o grupos de rutas:
Route::middleware(['admin'])->group(function () {
Route::get('/admin/dashboard', function () {
// Panel de administración
});
Route::get('/admin/usuarios', function () {
// Gestión de usuarios
});
});
De esta manera, todas las rutas dentro del grupo heredarán los middlewares definidos en el grupo admin
, asegurando que solo usuarios autorizados y con el rol adecuado accedan a ellas.
Además de los grupos, es importante comprender cómo Laravel maneja la prioridad de ejecución de los middlewares. Los middlewares pueden ser terminables o no terminables, y su orden de ejecución puede afectar el comportamiento de la aplicación.
Cuando varios middlewares están asignados a una ruta, Laravel los ejecuta en el orden en que aparecen en la lista. Sin embargo, cuando se utilizan middlewares globales, de grupo y de ruta simultáneamente, la prioridad puede ser más compleja.
Laravel proporciona la propiedad $middlewarePriority
en el archivo Kernel.php
, donde se define el orden en que los middlewares deben ser ejecutados. Este orden es crucial cuando ciertos middlewares dependen de otros, o cuando es necesario que uno se ejecute antes que otro para funcionar correctamente.
Un ejemplo de $middlewarePriority
podría ser:
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\Auth\Middleware\Authenticate::class,
\App\Http\Middleware\VerificarEdad::class,
\App\Http\Middleware\RegistrarActividad::class,
// Otros middlewares
];
En este caso, Laravel asegurará que el middleware StartSession
se ejecute antes que Authenticate
, y este antes que VerificarEdad
, y así sucesivamente. Esto es especialmente importante si un middleware requiere que otro haya sido ejecutado previamente, como cuando se necesita que la sesión esté iniciada antes de verificar la autenticación.
Es relevante destacar que, si no se especifica una prioridad, Laravel aplica los middlewares en el orden en que fueron registrados. Sin embargo, al utilizar grupos de middlewares, el orden dentro del grupo es respetado, pero los middlewares de la propiedad $middlewarePriority
tienen precedencia si hay conflicto.
Por ejemplo, si tenemos una ruta que utiliza tanto middlewares de grupo como individuales:
Route::middleware(['web', 'verificar.edad:18'])->group(function () {
Route::get('/contenido', function () {
// Contenido restringido
});
});
Aquí, el middleware verificar.edad
se aplicará después de los middlewares del grupo web
, siguiendo el orden establecido.
Para evitar conflictos y asegurar un flujo coherente, es buena práctica gestionar las prioridades adecuadamente, especialmente en aplicaciones complejas con numerosos middlewares.
En resumen, los grupos de middleware permiten simplificar la asignación de múltiples middlewares a rutas o controladores, mejorando la organización del código. Las prioridades de middleware garantizan que los middlewares se ejecuten en el orden correcto, asegurando la consistencia y correcta ejecución de la lógica de la aplicación.
Además, al combinar grupos de middlewares con middlewares individuales, podemos lograr un control preciso sobre cómo y cuándo se aplican las diferentes capas de lógica en nuestra aplicación Laravel.
Todas las lecciones de Laravel
Accede a todas las lecciones de Laravel y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Php Laravel
Introducción Y Entorno
Instalación Y Configuración Laravel
Introducción Y Entorno
Controladores Mvc
Controladores Http
Vistas Y Blade Templates
Controladores Http
Formularios Y Validación
Controladores Http
Controladores Rest
Controladores Http
Middleware Y Control De Solicitudes
Persistencia
Seguridad Autenticación Y Autorización
Persistencia
Bases De Datos Y Eloquent Orm
Persistencia
Relaciones Entre Modelos
Persistencia
Consultas Avanzadas
Persistencia
Colecciones Y Métodos Avanzados
Persistencia
Migraciones Y Seeders
Persistencia
Sistema De Autenticación Nativo Laravel
Middlewares Y Seguridad
Autorización (Policies Y Gates)
Middlewares Y Seguridad
Csrf Y Protección De Formularios En Blade
Middlewares Y Seguridad
Validaciones De Datos En Controladores Y Formularios
Middlewares Y Seguridad
Cifrado De Contraseñas
Middlewares Y Seguridad
Autenticación Jwt En Api Rest
Middlewares Y Seguridad
Pruebas Unitarias Con Phpunit
Testing
Pruebas De Integración En Laravel
Testing
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender el concepto y la función de los middleware en Laravel.
- Aprender a crear y registrar middleware personalizados.
- Diferenciar entre middleware globales y de ruta.
- Implementar grupos de middleware para una gestión eficiente.
- Manejar prioridades de ejecución entre distintos middleware.
- Aplicar middlewares dinámicamente a rutas o controladores.