5.16 Middleware en Laravel: Protegiendo APIs
5.16.1 Introducción
Un middleware en Laravel es una clase que actúa como un filtro entre la petición HTTP del cliente y el controlador que procesa esa petición. Su función principal es la de interceptar las peticiones y decidir si deben continuar o no hacia el siguiente paso del ciclo de vida de Laravel.
Los middlewares se utilizan para muchas tareas comunes:
- Verificar si el usuario está autenticado.
- Restringir el acceso según roles o permisos.
- Aplicar límites de peticiones por segundo.
- Registrar logs o realizar acciones antes o después de la petición.
¿Dónde se sitúa un middleware en el ciclo MVC?
graph TD
A[Petición HTTP] --> B[Middleware]
B --> C[Controlador]
C --> D[Modelo]
D --> E[Respuesta HTTP]
Como puedes ver, el middleware intercepta la petición antes de que llegue al controlador y también puede modificar la respuesta después.
5.16.2 Ubicación y estructura de los Middlewares
Los middlewares personalizados se encuentran en:
Laravel ya incluye muchos middlewares por defecto. Están registrados en app/Http/Kernel.php. Ahí se dividen en:
- Middlewares globales: se aplican a todas las rutas.
- Middlewares de grupo: se aplican a rutas
weboapisegún corresponda. - Middlewares individuales: se pueden asignar directamente a una ruta.
Algunos ejemplos comunes:
| Middleware | Descripción |
|---|---|
auth |
Verifica si el usuario está autenticado |
guest |
Redirige si el usuario ya está autenticado |
throttle |
Controla el número de peticiones por minuto |
verified |
Comprueba si el email está verificado |
signed |
Valida URLs firmadas |
5.16.3 Crear un Middleware personalizado
Mirar que la base de datos esté creada y vacía para que la migración inicial funcione sin problemas.
Vamos a crear un middleware simple que permita o no acceder a una ruta según el valor de una cabecera personalizada. Vamos a controlar una ruta de API. Por tanto lo primero será instalar el soporte de API:
Al final de la instalación nos pedirá que hagamos la miración le indicamos que sí o la hacemos manualmente al terminar la instalación.
Paso 1: Crear la clase middleware
Esto crea un archivo en app/Http/Middleware/EjemploMiddleware.php.
Esta va a ser un middleware sencillo, únicamente nos redirigirá a otra ruta.
Paso 2: Editar el middleware
Ejemplo de validación de cabecera HTTP
Paso 3: Registrar el middleware
En laravel 12 el registro de las rutas se hace en bootstrap/app.php.
Entramos en el fichero y añadimos el middleware a la propiedad $routeMiddleware:
| bootstrap/app.php | |
|---|---|
Ahora si queremos dar un alias al middleware para usarlo más fácilmente:
| bootstrap/app.php | |
|---|---|
Paso 4: Usar en las rutas
Creamos el controlador para manejar las rutas protegidas por el middleware:
Controlador de ejemplo para manejar rutas protegidas por middleware
Ahora vamos a definir las rutas que usaremos para probar el middleware. Vamos a crear dos rutas, una protegida por el middleware y otra a la que redirigiremos si no se cumple la condición del middleware.
Vamos a crear dos rutas:
/secret: protegida por el middleware. No se puede acceder./no-access: ruta a la que redirigimos si no se cumple la condición del middleware.
En routes/api.php:
Route::middleware('ejemplo')
->get('/secret', [SecretController::class, 'index'])
->name('secret.index');
Route::get('/no-access', [SecretController::class, 'noAccess'])
->name('no-access.index');
middleware no tiene condiciones, siempre redirigirá a la ruta /no-access.
Si intentamos acceder a /secret:
Nos redirigirá a:
Y nos devolverá error 403 y el JSON:
Puedes probar a quirtar el middleware y verás que ahora sí puedes acceder a la ruta /secret:
Paso 5: Aplicar el middleware a un grupo de rutas
Si quieres aplicar el middleware a un grupo de rutas, puedes hacerlo así:
Route::middleware('ejemplo')->group(function () {
Route::get('/secret', [SecretController::class, 'index'])
->name('secret.index');
Route::get('/secret2', [SecretController::class, 'index'])
->name('secret2.index');
Route::get('/no-access', [SecretController::class, 'noAccess'])
->name('no-access.index')->withoutMiddleware('ejemplo');
});
Podemos ver como agrupamos las rutas afectadas por el middleware. En caso de que no queramos aplicar el middleware a una ruta concreta, podemos usar el método withoutMiddleware para excluirla.
Si quermos aplicar más de un middleware a un grupo de rutas, podemos hacerlo así:
Route::middleware(['ejemplo', 'auth:sanctum'])->group(function () {
Route::get('/secret', [SecretController::class, 'index'])
->name('secret.index');
Route::get('/secret2', [SecretController::class, 'index'])
->name('secret2.index');
Route::get('/no-access', [SecretController::class, 'noAccess'])
->name('no-access.index')->withoutMiddleware('ejemplo');
});
auth:sanctum se aplicará a todas las rutas del grupo, y el middleware ejemplo se aplicará solo a las rutas /secret y /secret2.
5.16.4 Crear rutas API de autenticación
Vamos a crear una API de autenticación básica para registrarse, iniciar sesión. Utilizaremos tokens para identificar al usuario.
Para ello, Laravel recomienda usar Sanctum, que simplifica mucho la generación de tokens:
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
En config/sanctum.php, puedes ajustar la duración del token, pero lo dejamos por defecto.
Configurar el modelo User
En app/Models/User.php, asegurarse de usar el trait:
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
...
...
}
Paso 1: Crear un controlador de autenticación
Vamos a crear un controlador para manejar la autenticación. Puedes usar el comando:
Vamos a crear también un UserRequest para validar los datos de entrada:
también vamos a crear un LoginUserRequest para validar los datos de entrada:
Ahora que temos las dos clases de request, vamos a usarlas en el controlador:
Paso 2: Registro de usuario
Ahora que tenemos el diseño del controlador, vamos a crear las rutas para el registro y el login.
Vamos a crear las rutas en routes/api.php:
Route::post('/register', [AuthController::class, 'createUser'])
->name('register');
Route::post('/login', [AuthController::class, 'loginUser'])
->name('login');
Route::middleware('auth:sanctum')
->get('/user', function (Request $request) {
return $request->user();
})->name('user');
Para probar la API, puedes usar Postman o cualquier cliente REST.
Paso 3: Probar la API
Registro de usuario
Para registrar un usuario, envía una petición POST a la ruta /api/register con el siguiente cuerpo:
Login de usuario
Para iniciar sesión, envía una petición POST a la ruta /api/login con el siguiente cuerpo:
5.16.5 Ruta protegida por token con auth:sanctum
Ahora nos fijamos en la última ruta creada y que hemos protegido con el middleware auth:sanctum.
Route::->middleware('auth:sanctum')->get('/user', function (Request $request) {
return response()->json($request->user());
});
Esta ruta devuelve el usuario autenticado.
Para acceder:
- Hacer login y copiar el token.
- Enviar petición con la cabecera:
Si no se envía el token o es inválido, devuelve 401.
5.16.6 Consejos para probar desde Postman o REST Client
En Postman:
- Cabecera
Accept: application/json - Cabecera
Authorization: Bearer {token}
En REST Client (VS Code):
GET http://localhost:8080/api/test
###
POST http://localhost:8080/api/create HTTP/1.1
Content-Type: application/json
{
"name": "Test",
"email": "test@example.com",
"password": "password"
}
###
POST http://localhost:8080/api/login HTTP/1.1
Content-Type: application/json
{
"email": "test@example.com",
"password": "password"
}
###
POST http://localhost:8080/api/login HTTP/1.1
Content-Type: application/json
{
"email": "test@example.com",
"password": "bad_password"
}
###
GET http://localhost:8080/api/user HTTP/1.1
Authorization: Bearer 3|wKvMo8... (token)
Content-Type: application/json
5.16.7 Conclusiones
- Los middlewares permiten controlar el acceso y comportamiento de las peticiones.
- Pueden ser globales, por grupo o asignados a rutas.
- Laravel permite crear middlewares personalizados con facilidad.
- Para APIs, Laravel Sanctum es una forma segura y sencilla de implementar autenticación por token.
- Toda esta lógica la veremos más adelante también aplicada a rutas web, roles y protección por permisos.
Próximo tema: middleware aplicado a vistas web y roles de usuario.