Proteger rutas
Una vez que tienes autenticación en tu aplicación, necesitas restringir el acceso a ciertas páginas. Laravel usa middleware para proteger rutas, permitiendo que solo usuarios autenticados accedan a contenido privado.
El middleware auth
El middleware auth es el encargado de verificar
si un usuario está autenticado. Si no lo está, lo redirige
automáticamente a la página de login.
Este middleware viene incluido en Laravel y está registrado
en bootstrap/app.php. No necesitas crearlo ni
configurarlo manualmente.
Proteger una ruta individual
La forma más simple de proteger una ruta es encadenar
el método middleware():
<?php
use Illuminate\Support\Facades\Route;
// Ruta pública - cualquiera puede acceder
Route::get('/', function () {
return view('welcome');
});
// Ruta protegida - solo usuarios autenticados
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware('auth');
Si un usuario no autenticado intenta acceder a
/dashboard, Laravel lo redirige a
/login automáticamente.
Proteger múltiples rutas con grupos
Cuando tienes varias rutas que requieren autenticación, es más limpio agruparlas:
<?php
use App\Http\Controllers\ProfileController;
use App\Http\Controllers\SettingsController;
use Illuminate\Support\Facades\Route;
// Rutas públicas
Route::get('/', function () {
return view('welcome');
});
// Rutas protegidas
Route::middleware('auth')->group(function () {
Route::get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
Route::get('/profile', [ProfileController::class, 'edit'])
->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])
->name('profile.update');
Route::get('/settings', [SettingsController::class, 'index'])
->name('settings');
});
Todas las rutas dentro del grupo heredan el middleware
auth. Esto mantiene tu código organizado y
evita repetir ->middleware('auth') en cada ruta.
Combinar middleware auth con prefijos
Puedes combinar el middleware con prefijos de URL para organizar mejor tus rutas:
<?php
use App\Http\Controllers\Admin\DashboardController;
use App\Http\Controllers\Admin\UserController;
use Illuminate\Support\Facades\Route;
// Panel de administración
Route::middleware('auth')
->prefix('admin')
->name('admin.')
->group(function () {
// /admin/dashboard -> admin.dashboard
Route::get('/dashboard', [DashboardController::class, 'index'])
->name('dashboard');
// /admin/users -> admin.users.index
Route::get('/users', [UserController::class, 'index'])
->name('users.index');
// /admin/users/{user} -> admin.users.show
Route::get('/users/{user}', [UserController::class, 'show'])
->name('users.show');
});
El middleware verified
Además de auth, Laravel incluye el middleware
verified que verifica que el usuario haya
confirmado su email. Puedes combinar ambos:
<?php
// Solo usuarios autenticados Y con email verificado
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
Si el usuario no ha verificado su email, será redirigido a una página que le pide verificarlo.
Recuerda: Para que verified
funcione, tu modelo User debe implementar la interfaz
MustVerifyEmail (visto en la lección anterior).
Middleware en controladores con resource
Cuando usas rutas de tipo resource, puedes aplicar
middleware directamente al registrarlas. Por ejemplo,
si quieres que index y show
sean públicos pero el resto requiera autenticación:
<?php
use App\Http\Controllers\ArticleController;
use Illuminate\Support\Facades\Route;
// Rutas públicas del resource
Route::resource('articles', ArticleController::class)
->only(['index', 'show']);
// Rutas protegidas del resource
Route::resource('articles', ArticleController::class)
->except(['index', 'show'])
->middleware('auth');
También puedes separar las rutas en grupos para mayor claridad:
<?php
use App\Http\Controllers\PostController;
use Illuminate\Support\Facades\Route;
// Cualquiera puede ver posts
Route::get('/posts', [PostController::class, 'index'])->name('posts.index');
Route::get('/posts/{post}', [PostController::class, 'show'])->name('posts.show');
// Solo usuarios autenticados pueden crear/editar/eliminar
Route::middleware('auth')->group(function () {
Route::get('/posts/create', [PostController::class, 'create'])->name('posts.create');
Route::post('/posts', [PostController::class, 'store'])->name('posts.store');
Route::get('/posts/{post}/edit', [PostController::class, 'edit'])->name('posts.edit');
Route::put('/posts/{post}', [PostController::class, 'update'])->name('posts.update');
Route::delete('/posts/{post}', [PostController::class, 'destroy'])->name('posts.destroy');
});
El middleware guest
El middleware guest es lo opuesto a
auth: solo permite acceso a usuarios
no autenticados. Es útil para páginas
como login o registro, donde no tiene sentido que un
usuario ya autenticado las vea:
<?php
use App\Http\Controllers\Auth\LoginController;
use App\Http\Controllers\Auth\RegisterController;
// Solo para usuarios no autenticados
Route::middleware('guest')->group(function () {
Route::get('/login', [LoginController::class, 'create'])
->name('login');
Route::post('/login', [LoginController::class, 'store']);
Route::get('/register', [RegisterController::class, 'create'])
->name('register');
Route::post('/register', [RegisterController::class, 'store']);
});
Si un usuario autenticado intenta acceder a /login,
será redirigido al dashboard (o a la ruta configurada en
RouteServiceProvider).
Personalizar la redirección
Por defecto, cuando un usuario no autenticado intenta
acceder a una ruta protegida, Laravel lo redirige a
/login. Puedes cambiar esto en
bootstrap/app.php:
<?php
// bootstrap/app.php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
)
->withMiddleware(function (Middleware $middleware) {
$middleware->redirectGuestsTo('/iniciar-sesion');
$middleware->redirectUsersTo('/panel');
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();
Con esta configuración:
redirectGuestsTo: A dónde enviar usuarios no autenticados que intentan acceder a rutas protegidasredirectUsersTo: A dónde enviar usuarios autenticados que intentan acceder a rutas de invitado (como login)
Redirección inteligente con intended
Cuando un usuario intenta acceder a una página protegida,
Laravel guarda la URL a la que quería ir. Después de hacer
login, puedes redirigirlo a esa URL con intended():
<?php
declare(strict_types=1);
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
public function store(Request $request): RedirectResponse
{
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (Auth::attempt($credentials)) {
$request->session()->regenerate();
// Redirige a la URL original o al dashboard
return redirect()->intended(route('dashboard'));
}
return back()->withErrors([
'email' => 'Las credenciales no coinciden.',
]);
}
}
Por ejemplo: el usuario intenta ir a /settings,
es redirigido a /login, hace login, y
automáticamente es llevado a /settings
(no al dashboard).
Verificar autenticación en vistas
En tus plantillas Blade, puedes usar directivas para mostrar contenido según el estado de autenticación:
<nav>
@auth
{{-- Usuario autenticado --}}
<span>Hola, {{ auth()->user()->name }}</span>
<a href="{{ route('dashboard') }}">Panel</a>
<form method="POST" action="{{ route('logout') }}">
@csrf
<button type="submit">Cerrar sesión</button>
</form>
@else
{{-- Usuario invitado --}}
<a href="{{ route('login') }}">Iniciar sesión</a>
<a href="{{ route('register') }}">Registrarse</a>
@endauth
</nav>
También existe @guest para el caso contrario:
@guest
<p>Bienvenido. Por favor, inicia sesión para continuar.</p>
@endguest
Acceder al usuario autenticado
En tus controladores y vistas, puedes acceder al usuario autenticado de varias formas:
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
// En un controlador
// Opción 1: Facade Auth
$user = Auth::user();
$userId = Auth::id();
// Opción 2: Helper auth()
$user = auth()->user();
$userId = auth()->id();
// Opción 3: Desde el Request (recomendado en controladores)
public function show(Request $request)
{
$user = $request->user();
return view('profile', compact('user'));
}
// Verificar si hay usuario autenticado
if (Auth::check()) {
// Usuario autenticado
}
// O con el helper
if (auth()->check()) {
// Usuario autenticado
}
Resumen
- El middleware
authprotege rutas para usuarios autenticados - Aplícalo con
->middleware('auth')en rutas individuales - Usa
Route::middleware('auth')->group()para agrupar varias rutas - El middleware
verifiedrequiere email verificado - El middleware
guestes para usuarios no autenticados - Con rutas resource, usa
->only()y->except()para controlar qué rutas proteger - Usa
redirect()->intended()para volver a la URL original tras login - Las directivas
@authy@guestcontrolan contenido en vistas
Ejercicios
Ejercicio 1: Crear un área privada
Crea tres rutas protegidas: /account,
/account/orders y /account/settings.
Todas deben requerir autenticación y usar el prefijo
"account" con nombres de ruta apropiados.
Ver solución
<?php
// routes/web.php
use Illuminate\Support\Facades\Route;
Route::middleware('auth')
->prefix('account')
->name('account.')
->group(function () {
Route::get('/', function () {
return view('account.index');
})->name('index');
Route::get('/orders', function () {
return view('account.orders');
})->name('orders');
Route::get('/settings', function () {
return view('account.settings');
})->name('settings');
});
// Resultado:
// GET /account -> account.index
// GET /account/orders -> account.orders
// GET /account/settings -> account.settings
Ejercicio 2: Rutas resource con middleware parcial
Configura las rutas para un PostController
donde index y show sean
públicos, pero create, store,
edit, update y destroy
requieran autenticación. Usa rutas resource.
Ver solución
<?php
// routes/web.php
use App\Http\Controllers\PostController;
use Illuminate\Support\Facades\Route;
// Rutas públicas: listar y ver posts
Route::resource('posts', PostController::class)
->only(['index', 'show']);
// Rutas protegidas: crear, editar, eliminar posts
Route::resource('posts', PostController::class)
->except(['index', 'show'])
->middleware('auth');
<?php
// app/Http/Controllers/PostController.php
declare(strict_types=1);
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class PostController extends Controller
{
public function index(): View
{
$posts = Post::latest()->paginate(10);
return view('posts.index', compact('posts'));
}
public function show(Post $post): View
{
return view('posts.show', compact('post'));
}
public function create(): View
{
return view('posts.create');
}
public function store(Request $request): RedirectResponse
{
$validated = $request->validate([
'title' => ['required', 'max:255'],
'content' => ['required'],
]);
$request->user()->posts()->create($validated);
return redirect()->route('posts.index');
}
public function edit(Post $post): View
{
return view('posts.edit', compact('post'));
}
public function update(Request $request, Post $post): RedirectResponse
{
$validated = $request->validate([
'title' => ['required', 'max:255'],
'content' => ['required'],
]);
$post->update($validated);
return redirect()->route('posts.show', $post);
}
public function destroy(Post $post): RedirectResponse
{
$post->delete();
return redirect()->route('posts.index');
}
}
Ejercicio 3: Navegación dinámica
Crea un componente de navegación Blade que muestre enlaces diferentes según si el usuario está autenticado o no. Para usuarios autenticados: Dashboard, Perfil y botón Cerrar sesión. Para invitados: Iniciar sesión y Registrarse.
Ver solución
{{-- resources/views/components/navigation.blade.php --}}
<nav class="main-nav">
<a href="{{ url('/') }}">Inicio</a>
@auth
<a href="{{ route('dashboard') }}">Dashboard</a>
<a href="{{ route('profile.edit') }}">
{{ auth()->user()->name }}
</a>
<form method="POST" action="{{ route('logout') }}" class="inline">
@csrf
<button type="submit">Cerrar sesión</button>
</form>
@else
<a href="{{ route('login') }}">Iniciar sesión</a>
<a href="{{ route('register') }}">Registrarse</a>
@endauth
</nav>
{{-- Usar en el layout principal --}}
<!DOCTYPE html>
<html>
<head>
<title>Mi App</title>
</head>
<body>
<x-navigation />
<main>
{{ $slot }}
</main>
</body>
</html>
¿Has encontrado un error o tienes una sugerencia para mejorar esta lección?
Escríbenos¿Te está gustando el curso?
Tenemos cursos premium con proyectos reales, soporte personalizado y certificado.
Descubrir cursos premium