404 Not Found

404 Not Found


nginx

Middleware

Bob descobriu que Alice poderia acessar diretamente o painel administrativo /admin sem nenhuma verificação de permissão. Charlie precisa de um guardião de rota — que redirecione automaticamente usuários não autenticados que tentam acessar a página de administração para a página de login, e impeça usuários comuns de acessar rotas administrativas. O sistema de middleware do Nuxt 3 é a solução.

1. O Que Você Vai Aprender


2. Uma História Real de um Administrador

(1) Ponto Crítico: Uma Vulnerabilidade Crítica Devido à Falta de Controle de Permissão

Alice digitou /admin no navegador e acessou o painel administrativo do MegaShop, onde podia ver todos os pedidos e dados de usuários. Bob, como administrador, descobriu que a interface que via era exatamente igual à de um usuário comum, sem nenhuma distinção. Charlie precisava urgentemente de controle de acesso em nível de rota.

(2) Solução com Middleware de Rota

No Nuxt 3, o middleware é executado antes de uma transição de rota e pode redirecionar ou bloquear o acesso:

TYPESCRIPT
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to) => {
  if (!isAuthenticated()) return navigateTo('/login')
})

(3) Benefícios: Controle de Acesso em Nível de Rota

Alice não pode mais acessar /admin diretamente; se não estiver logada, é redirecionada automaticamente para a página de login. Os privilégios de administrador de Bob são aplicados em nível de rota.


3. Três Padrões de Middleware

(1) Ordem de Execução do Middleware

100%
flowchart LR
    A[Route Navigation] --> B[Global Middleware 1]
    B --> C[Global Middleware 2]
    C --> D[Named/Inline Middleware]
    D --> E[Page Render]
    D -->|abort| F[Redirect / Abort]
    B -->|abort| F
    C -->|abort| F

(2) Comparação dos Três Modelos

Dimensão Middleware Global Middleware Nomeado Middleware Inline
Nome do Arquivo *.global.ts *.ts (sem "global") Sem arquivo
Escopo Todas as Rotas Páginas Específicas Página Atual
Método de Definição diretório middleware/ diretório middleware/ dentro de definePageMeta
Reusabilidade ✅ Reuso automático ✅ Referência em múltiplas páginas ❌ Somente na página atual
Casos de Uso Autenticação/Logging Global Guarda Específica de Página Verificação Simples Única

4. Middleware Global

(1) ▶Exemplo: Middleware de Autenticação Global

TYPESCRIPT
// middleware/auth.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
  // Pular autenticação para páginas públicas
  const publicPages = ['/', '/products', '/about', '/login', '/register']
  if (publicPages.includes(to.path)) return

  const token = useCookie('auth-token')
  if (!token.value) {
    return navigateTo(`/login?redirect=${to.path}`, { redirectCode: 302 })
  }
})

Saída:

TEXT
// Execução Bem-sucedida

(2) ▶Exemplo: Middleware de Log Global

TYPESCRIPT
// middleware/log.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
  console.log(`Navegação: ${from.path} → ${to.path}`)
  // Sem retorno = permitir navegação
})

Saída:

TEXT
// Execução Bem-sucedida
⚠️ Nota: O middleware global é executado em ordem alfabética pelo nome do arquivo. 01-auth.global.ts executa antes de 02-log.global.ts. Recomendamos usar um prefixo numérico para controlar a ordem.


5. Middleware Nomeado

(1) ▶Exemplo: Middleware de Papel de Administrador

TYPESCRIPT
// middleware/admin.ts
export default defineNuxtRouteMiddleware((to) => {
  const user = useState('user')

  if (!user.value) {
    return navigateTo(`/login?redirect=${to.path}`)
  }

  if (user.value.role !== 'admin') {
    // Usuário comum tentando acessar página de administração
    throw createError({
      statusCode: 403,
      message: 'Access denied. Admin role required.'
    })
  }
})

Saída:

TEXT
// Execução Bem-sucedida

(2) ▶Exemplo: Referenciando um middleware nomeado em uma página

VUE
<!-- pages/admin/index.vue -->
<template>
  <div>
    <h1>Admin Dashboard</h1>
    <p>Welcome, Bob (Admin)</p>
  </div>
</template>

<script setup lang="ts">
definePageMeta({
  middleware: 'admin', // Referenciar middleware nomeado
  layout: 'sidebar'
})
</script>

Saída:

TEXT
// Execução Bem-sucedida

(3) ▶Exemplo: Combinando Múltiplos Middleware

VUE
<!-- pages/admin/settings.vue -->
<template>
  <div>
    <h1>Admin Settings</h1>
  </div>
</template>

<script setup lang="ts">
definePageMeta({
  middleware: ['auth', 'admin'], // Executar em ordem: auth → admin
  layout: 'sidebar'
})
</script>

Saída:

TEXT
// Execução Bem-sucedida

6. Middleware Inline

(1) ▶Exemplo: Definindo middleware dentro de uma página

VUE
<!-- pages/checkout.vue -->
<template>
  <div>
    <h1>Checkout</h1>
    <p>Cart total: ${{ total }} USD</p>
  </div>
</template>

<script setup lang="ts">
definePageMeta({
  middleware: defineNuxtRouteMiddleware((to) => {
    // Inline: verificar se o carrinho tem itens
    const cart = useState<any[]>('cart')
    if (cart.value.length === 0) {
      return navigateTo('/cart')
    }
  })
})

const cart = useState<any[]>('cart')
const total = computed(() => cart.value.reduce((s, i) => s + i.price, 0))
</script>

Saída:

TEXT
// Execução Bem-sucedida

(1) Escolhendo Entre Middleware Inline e Nomeado

Cenário Escolha Motivo
Autenticação em todo o site Global Verificar toda rota
Rotas Administrativas Nomeado Compartilhado por Múltiplas Páginas Admin
Verificar se o carrinho não está vazio Inline Usar apenas na página de checkout
Área VIP Nomeado Pode ser usado em múltiplas páginas
Teste A/B de Divisão de Tráfego Inline Lógica Única

7. Middleware e SSR

(1) Mecanismo de Dupla Execução SSR

100%
flowchart TB
    A[User navigates to /admin] --> B[Server: middleware executes]
    B -->|redirect| C[Server sends redirect response]
    B -->|allow| D[Server renders page]
    D --> E[Client: middleware executes again]
    E -->|redirect| F[Client-side redirect]
    E -->|allow| G[Client hydrates page]

(1) ▶Exemplo: Middleware Somente no Cliente

TYPESCRIPT
// middleware/client-only.ts
export default defineNuxtRouteMiddleware((to) => {
  // Pular no servidor - verificar apenas no cliente
  if (import.meta.server) return

  const localStorage = window.localStorage
  const preferences = JSON.parse(localStorage.getItem('user-preferences') || '{}')

  if (preferences.theme === 'dark') {
    // Lógica somente no cliente usando APIs do navegador
    document.documentElement.classList.add('dark')
  }
})

Saída:

TEXT
// Execução Bem-sucedida

(2) Considerações para Middleware SSR

Problema Causa Solução
Middleware executa duas vezes SSR e cliente executam uma vez cada Comportamento esperado; garantir idempotência
Usando window/localStorage SSR (sem ambiente de navegador) Verificação com if (import.meta.client)
Cookies estão disponíveis no SSR Requisições carregam cookies Lidos usando useCookie
navigateTo no SSR Retorna um redirecionamento 302 Comportamento esperado
useState no middleware ✅ Disponível Adequado para verificar status de login

8. Exemplo Completo: O Sistema de Guarda de Permissões do MegaShop

TYPESCRIPT
// middleware/01-auth.global.ts - Verificação global de autenticação
export default defineNuxtRouteMiddleware((to) => {
  const publicPaths = ['/', '/products', '/products/**', '/about', '/login', '/register']
  const isPublic = publicPaths.some(path => {
    if (path.includes('')) return to.path.startsWith(path.replace('/', ''))
    return path === to.path
  })

  if (isPublic) return

  const token = useCookie('auth-token')
  if (!token.value) {
    return navigateTo(`/login?redirect=${encodeURIComponent(to.path)}`)
  }
})
TYPESCRIPT
// middleware/admin.ts - Verificação de papel de administrador
export default defineNuxtRouteMiddleware((to) => {
  const user = useCookie('user-data')

  if (!user.value) {
    return navigateTo('/login')
  }

  if ((user.value as any).role !== 'admin') {
    throw createError({ statusCode: 403, message: 'Admin access required' })
  }
})
VUE
<!-- pages/admin/products/index.vue -->
<template>
  <div>
    <h1>Product Management</h1>
    <p>Manage 1 million products</p>
    <!-- Interface CRUD de produtos administrativos -->
  </div>
</template>

<script setup lang="ts">
definePageMeta({
  middleware: ['admin'],
  layout: 'sidebar'
})
</script>

❓Perguntas Frequentes

P Como a ordem de execução do middleware é controlada?
R O middleware global é ordenado alfabeticamente pelo nome do arquivo; recomendamos usar um prefixo numérico (01-xxx.global.ts). O middleware nomeado é executado na ordem especificada no array dentro de definePageMeta.
P Operações assíncronas podem ser realizadas no middleware?
R defineNuxtRouteMiddleware em si não suporta async. No entanto, você pode chamar APIs síncronas (como useCookie ou useState) dentro do middleware. Se precisar realizar validação assíncrona, é recomendável tratá-la em um plugin ou no método setup da página.
P Por que o middleware é executado uma vez durante SSR e uma vez no lado do cliente?
R Durante o SSR, o middleware verifica as permissões de rota para determinar se a página deve ser renderada; ele é executado novamente durante a hidratação no cliente para garantir consistência. A lógica de ambas as execuções deve ser idempotente.
P O middleware global afeta o desempenho?
R Todo middleware global é executado a cada navegação de rota. Mantenha a lógica do middleware leve e evite realizar computações pesadas ou chamadas de API no middleware global.
P O que acontece se um createError for lançado no middleware?
R Durante o SSR, uma página de erro HTML com o código de status correspondente é retornada (por exemplo, uma página 403). No lado do cliente, a página de erro do Nuxt é exibida. Você pode personalizar error.vue.
P Como passar dados entre middleware?
R Use useState ou a propriedade payload de NuxtApp. const nuxtApp = useNuxtApp()nuxtApp.payload.xxx = data. O próximo middleware ou página pode acessá-lo.

📖Resumo


📝Exercícios

  1. Exercício Básico (Dificuldade: ⭐): Crie um middleware chamado guest.ts que permita apenas usuários não autenticados acessar a página (usuários logados são redirecionados para a página inicial), e aplique-o à página /login.
  2. Exercício Avançado (Dificuldade ⭐⭐): Implemente um sistema completo de autorização: verificação global de autenticação para login + verificação de papel para o usuário "admin"; a rota /admin/** é protegida.
  3. Desafio (Dificuldade: ⭐⭐⭐): Implemente a passagem de dados entre middleware — obtenha informações do usuário no middleware auth e armazene-as no payload do NuxtApp, depois leia-as diretamente no middleware admin para evitar requisições duplicadas.

---|

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%