Laravel Middleware em profundidade: Autenticação, Rate Limiting e Middleware personalizado

Guia completo sobre middleware no Laravel com exemplos práticos: guards de autenticação, limitação de taxa com throttle, criação de middleware personalizado e padrões avançados para aplicações em produção.

Arquitetura de middleware do Laravel mostrando o pipeline de requisições com camadas de autenticação e limitação de taxa

O middleware do Laravel funciona como uma camada de filtragem entre as requisições HTTP recebidas e a lógica da aplicação. Cada requisição percorre um pipeline de classes middleware antes de chegar a um controller, e cada resposta viaja de volta pelo mesmo pipeline. Compreender esse mecanismo é fundamental para construir aplicações Laravel seguras e de alto desempenho em 2026.

Middleware em resumo

O middleware intercepta requisições HTTP antes que elas alcancem as rotas. O Laravel 12 registra todos os middleware em bootstrap/app.php usando uma API fluente. Os middleware integrados gerenciam autenticação, proteção CSRF, gerenciamento de sessões e limitação de taxa nativamente.

Como funciona o pipeline de middleware no Laravel

O kernel HTTP do Laravel processa cada requisição através de uma pilha de middleware. Cada middleware recebe a requisição, executa sua lógica e então passa a requisição para a próxima camada via $next($request) ou interrompe o pipeline retornando uma resposta diretamente.

Essa arquitetura segue o padrão de projeto Chain of Responsibility. Um middleware pode atuar antes de a requisição alcançar o controller (por exemplo, verificações de autenticação), depois que a resposta é gerada (por exemplo, adicionando cabeçalhos), ou em ambos os momentos.

app/Http/Middleware/LogRequestTime.phpphp
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
    }
}

Esse middleware envolve a requisição: ele registra o tempo de início antes do processamento e registra a duração depois que a resposta retorna. Esse padrão antes/depois é central no funcionamento dos middleware.

Middleware de autenticação: protegendo rotas

O Laravel inclui o alias de middleware auth, mapeado para Illuminate\Auth\Middleware\Authenticate. Ao aplicá-lo a uma rota, apenas usuários autenticados conseguem acessá-la. Usuários não autenticados recebem uma resposta 401 (API) ou são redirecionados para a página de login (web).

routes/web.phpphp
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']);
});

Autenticação com múltiplos guards

Aplicações com vários tipos de usuários (painel administrativo, área do cliente, API) se beneficiam da autenticação baseada em guards. O middleware auth aceita um parâmetro de guard para especificar qual driver de autenticação deve ser utilizado.

routes/api.phpphp
// 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']);
});

O parâmetro de guard após os dois pontos indica ao Laravel qual configuração de autenticação verificar. Essa abordagem mantém a lógica de autenticação organizada e separada entre as diferentes partes da aplicação.

Middleware Guest

O middleware guest é o inverso do auth — permite a passagem apenas de usuários não autenticados. Ao aplicá-lo às rotas de login e cadastro, impede-se que usuários já autenticados acessem essas páginas.

Limitação de taxa com o middleware Throttle

A limitação de taxa via middleware no Laravel protege as rotas contra abusos usando o middleware integrado throttle. Sua forma mais simples aceita dois parâmetros: o número máximo de requisições e a janela de tempo em minutos.

routes/api.phpphp
// 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 nomeados para controle avançado

Definir rate limiters nomeados no AppServiceProvider oferece controle granular sobre os limites com base no contexto do usuário. Essa abordagem é mais flexível do que os parâmetros throttle inline.

app/Providers/AppServiceProvider.phpphp
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);
            });
    });
}

A aplicação de limiters nomeados às rotas utiliza a sintaxe throttle:name:

routes/api.phpphp
Route::middleware('throttle:api')->group(function () {
    Route::apiResource('/posts', PostController::class);
});

// routes/web.php
Route::middleware('throttle:login')
    ->post('/login', [AuthController::class, 'login']);

O rate limiter escalonado acima demonstra um padrão de produção: usuários enterprise obtêm limites mais altos, usuários autenticados recebem limites moderados, e requisições anônimas são restringidas de forma agressiva. O método by() determina a chave de limitação — usando o ID do usuário para usuários autenticados e o endereço IP como fallback.

Pronto para mandar bem nas entrevistas de Laravel?

Pratique com nossos simuladores interativos, flashcards e testes tecnicos.

Criando middleware personalizado do zero

A criação de middleware personalizado cobre cenários que os middleware integrados não tratam. O comando Artisan make:middleware gera uma nova classe com a estrutura correta.

bash
php artisan make:middleware EnsureUserHasRole

Middleware de controle de acesso baseado em papéis

Um padrão comum de middleware personalizado aplica autorização baseada em papéis no nível da rota, aceitando nomes de papéis como parâmetros.

app/Http/Middleware/EnsureUserHasRole.phpphp
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);
    }
}

O parâmetro variádico ...$roles permite passar múltiplos papéis separados por vírgulas. O registro e a utilização ficam assim:

bootstrap/app.phpphp
->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 transformação de requisições

Um middleware pode modificar a requisição antes que ela alcance o controller. A seguir, um middleware para API JSON que impõe cabeçalhos de tipo de conteúdo e limpa as entradas do tipo string:

app/Http/Middleware/ApiRequestSanitizer.phpphp
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);
    }
}

Esse middleware cuida de duas responsabilidades: valida o tipo de conteúdo para requisições POST e sanitiza todas as entradas de texto removendo espaços em branco desnecessários.

Registro de middleware no Laravel 12

O Laravel 12 centraliza todo o registro de middleware no arquivo bootstrap/app.php. Essa abordagem substituiu o antigo app/Http/Kernel.php que existia antes do Laravel 11.

bootstrap/app.phpphp
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();

O array priority é importante quando múltiplos middleware são atribuídos à mesma rota. O Laravel os ordena de acordo com essa lista, garantindo que a sessão seja iniciada antes da autenticação, e que a autenticação seja concluída antes das verificações de papel.

Ordem de execução dos middleware

Os middleware são executados na ordem de registro. Para middleware de rota, o array priority sobrescreve a ordem padrão. A autenticação deve ser sempre posicionada antes da autorização para evitar verificar papéis em requisições não autenticadas.

Middleware terminável para tarefas pós-resposta

O middleware terminável executa lógica após a resposta ter sido enviada ao cliente. Isso é particularmente útil para tarefas de logging, analytics ou limpeza que não devem bloquear o usuário.

app/Http/Middleware/CollectAnalytics.phpphp
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(),
        ]);
    }
}

O método terminate recebe tanto a requisição original quanto a resposta final. Recomenda-se registrar esse middleware como singleton no AppServiceProvider para garantir que a mesma instância trate tanto handle() quanto terminate().

Padrões de middleware para produção

Diversos padrões de middleware aparecem consistentemente em aplicações Laravel em produção.

Bypass do modo de manutenção — permitir que IPs internos acessem a aplicação durante a manutenção:

app/Http/Middleware/MaintenanceBypass.phpphp
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);
    }
}

Cabeçalhos de segurança — adicionar HSTS, política de segurança de conteúdo e outros cabeçalhos a cada resposta:

app/Http/Middleware/SecurityHeaders.phpphp
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;
    }
}

Esses padrões ilustram as duas posições principais dos middleware: antes da requisição (o bypass de manutenção verifica o IP e potencialmente bloqueia o acesso) e depois da resposta (os cabeçalhos de segurança modificam a resposta de saída).

Pronto para mandar bem nas entrevistas de Laravel?

Pratique com nossos simuladores interativos, flashcards e testes tecnicos.

Conclusão

  • O middleware do Laravel opera como um pipeline: cada classe processa a requisição, atua sobre ela e a passa adiante ou interrompe o fluxo com uma resposta
  • O middleware auth protege rotas com autenticação baseada em guards, suportando múltiplos tipos de usuários via sintaxe auth:guard
  • A limitação de taxa através do middleware throttle e das definições nomeadas RateLimiter::for() permite controle de acesso escalonado com base no contexto do usuário
  • Os middleware personalizados tratam preocupações transversais como verificações de papel, sanitização de requisições e cabeçalhos de segurança sem sobrecarregar os controllers
  • Todo o registro de middleware no Laravel 12 acontece em bootstrap/app.php usando uma API fluente, com priority controlando a ordem de execução
  • O middleware terminável executa tarefas pós-resposta (analytics, logging) sem impactar a latência percebida pelo usuário
  • Os parâmetros de middleware via sintaxe :param mantêm as definições de rota expressivas e as classes middleware reutilizáveis em diferentes contextos

Comece a praticar!

Teste seus conhecimentos com nossos simuladores de entrevista e testes tecnicos.

Tags

#laravel
#middleware
#authentication
#rate-limiting
#php

Compartilhar

Artigos relacionados