Middlewares e autenticação no Laravel
1. Fundamentos dos Middlewares no Laravel
Middlewares são camadas intermediárias que filtram requisições HTTP antes que elas atinjam o controller. No ecossistema PHP, o Laravel implementa esse padrão de forma elegante, permitindo inspecionar, modificar ou bloquear requisições conforme regras de negócio.
Para criar um middleware personalizado, utilize o Artisan:
php artisan make:middleware CheckUserRole
O arquivo gerado em app/Http/Middleware/CheckUserRole.php contém o método handle():
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class CheckUserRole
{
public function handle(Request $request, Closure $next, string $role): mixed
{
if (!$request->user() || !$request->user()->hasRole($role)) {
abort(403, 'Acesso não autorizado.');
}
return $next($request);
}
}
O registro pode ser feito de três formas:
- Globais: no array
$middlewaredo Kernel, aplicam-se a todas as rotas. - Grupos: no array
$middlewareGroups(ex:web,api). - Nomeados: no array
$routeMiddleware, permitindo uso direto nas rotas.
// app/Http/Kernel.php
protected $routeMiddleware = [
'role' => \App\Http\Middleware\CheckUserRole::class,
];
2. Mecanismos de Funcionamento dos Middlewares
O ciclo de vida de uma requisição no Laravel segue uma pilha de middlewares. O código antes de return $next($request) executa antes do controller; o código após, depois.
public function handle(Request $request, Closure $next): mixed
{
// Antes do controller
Log::info('Requisição recebida: ' . $request->path());
$response = $next($request);
// Depois do controller
Log::info('Resposta enviada: ' . $response->getStatusCode());
return $response;
}
Middlewares podem receber parâmetros adicionais, como vimos com $role. Outro exemplo prático é limitar acesso por horário:
// Rota
Route::get('/admin', function () {
return 'Painel administrativo';
})->middleware('check.hour:08:00,18:00');
3. Middlewares Nativos Essenciais
O Laravel fornece middlewares prontos que resolvem problemas comuns de autenticação e segurança:
// Proteger rotas autenticadas
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware('auth');
// Rotas apenas para visitantes não autenticados
Route::get('/login', function () {
return view('auth.login');
})->middleware('guest');
// Limitar requisições (ex: 10 por minuto)
Route::post('/api/upload', function () {
// ...
})->middleware('throttle:10,1');
// Exigir e-mail verificado
Route::get('/settings', function () {
return view('settings');
})->middleware(['auth', 'verified']);
// Confirmar senha antes de ação sensível
Route::post('/delete-account', function () {
// ...
})->middleware('password.confirm');
4. Autenticação com o Scaffold do Laravel
Para agilizar o desenvolvimento, o Laravel oferece pacotes de scaffolding. O Laravel Breeze é a opção mais leve e moderna:
composer require laravel/breeze --dev
php artisan breeze:install blade
php artisan migrate
npm install && npm run dev
Isso gera controllers como LoginController, RegisterController e views Blade completas. A estrutura gerada segue o padrão:
// app/Http/Controllers/Auth/AuthenticatedSessionController.php
public function store(LoginRequest $request): RedirectResponse
{
$request->authenticate();
$request->session()->regenerate();
return redirect()->intended(RouteServiceProvider::HOME);
}
Para personalizar o fluxo, basta modificar os controllers ou publicar as views:
php artisan vendor:publish --tag=laravel-breeze-views
5. Guards e Providers de Autenticação
O Laravel suporta múltiplos sistemas de autenticação simultaneamente. A configuração fica em config/auth.php:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'sanctum',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
],
Os providers definem como os usuários são recuperados:
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'admins' => [
'driver' => 'database',
'table' => 'admins',
],
],
A diferença entre autenticação stateful (sessão) e stateless (tokens) é crucial:
- Stateful: mantém estado via sessão PHP, ideal para aplicações web tradicionais.
- Stateless: cada requisição carrega um token, comum em APIs REST.
6. Proteção de Rotas com Middleware de Autenticação
Aplicar middlewares em rotas é simples e flexível:
// Em uma rota específica
Route::get('/profile', [ProfileController::class, 'show'])->middleware('auth');
// Em grupos de rotas
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index']);
Route::resource('/posts', PostController::class);
});
// Com Gate para autorização granular
Route::put('/posts/{post}', function (Post $post) {
$this->authorize('update', $post);
// ...
})->middleware('auth');
Para redirecionamento personalizado, modifique o método redirectTo() no App\Http\Middleware\Authenticate.php:
protected function redirectTo(Request $request): ?string
{
if (!$request->expectsJson()) {
return route('login.custom');
}
}
7. Autenticação via API com Sanctum
O Laravel Sanctum é a solução oficial para autenticação de APIs e SPAs. Instalação:
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
Para emitir tokens:
// UserController.php
public function login(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required',
]);
if (!Auth::attempt($request->only('email', 'password'))) {
return response()->json(['message' => 'Credenciais inválidas'], 401);
}
$user = Auth::user();
$token = $user->createToken('api-token')->plainTextToken;
return response()->json(['token' => $token]);
}
Proteção de rotas:
// api.php
Route::middleware('auth:sanctum')->group(function () {
Route::get('/user', function (Request $request) {
return $request->user();
});
Route::post('/posts', [PostController::class, 'store']);
});
Para SPAs, o Sanctum utiliza cookies de sessão, dispensando tokens explícitos:
// config/sanctum.php
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,localhost:3000')),
8. Boas Práticas e Depuração
Organize middlewares em módulos para aplicações grandes:
// app/Http/Middleware/Admin/VerifyAdmin.php
namespace App\Http\Middleware\Admin;
class VerifyAdmin
{
public function handle($request, Closure $next)
{
if (!$request->user()->isAdmin()) {
abort(403);
}
return $next($request);
}
}
Testes com PHPUnit garantem que middlewares funcionem corretamente:
public function test_middleware_blocks_unauthorized_access()
{
$response = $this->get('/admin/dashboard');
$response->assertRedirect('/login');
$user = User::factory()->create();
$response = $this->actingAs($user)->get('/admin/dashboard');
$response->assertStatus(403);
}
Para depuração, utilize logs estratégicos:
Log::channel('auth')->info('Falha de autenticação', [
'ip' => $request->ip(),
'email' => $request->email,
'time' => now(),
]);
Referências
- Documentação oficial de Middlewares no Laravel — Guia completo sobre criação, registro e uso de middlewares no Laravel.
- Documentação oficial de Autenticação no Laravel — Referência completa sobre guards, providers e fluxos de autenticação.
- Laravel Breeze - Documentação — Tutorial oficial de instalação e personalização do scaffolding de autenticação.
- Laravel Sanctum - Documentação — Guia oficial para autenticação de APIs e SPAs com tokens e cookies.
- Laravel Authorization (Gates & Policies) — Documentação sobre autorização com Gates, Policies e middleware
can. - Testes de Middlewares no Laravel - Laravel News — Artigo técnico sobre como testar middlewares com PHPUnit no Laravel.
- Autenticação Multi-Guard no Laravel - Laravel Daily — Tutorial prático sobre configuração de múltiplos guards e providers personalizados.