You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js生产环境App Router中间件未正常执行问题

Next.js 14 App Router 中间件生产环境认证失效问题修复

问题背景

将项目从 Pages Router 迁移到 App Router 后,使用了(main)和(auth)两个路由组分别对应首页/和认证页/auth,中间件逻辑为:

  • 未认证用户访问/时自动跳转至/auth
  • 已认证用户访问/auth时自动跳转至/
    该逻辑在本地开发环境正常,但生产环境下出现校验失效,未认证用户偶尔能访问/,已认证用户偶尔能访问/auth。

项目采用src目录结构,middleware.ts与src/app同级,目录结构如下:

|-- src
|--- app
|---- (main)
|----- layout.tsx
|----- page.tsx
|---- (auth)
|----- layout.tsx
|----- page.tsx
|---- layout.tsx
|--- middleware.ts

核心问题分析

  1. 生产环境静态缓存:App Router 对静态页面默认启用缓存,若page.tsx未配置动态渲染,生产环境会直接返回缓存页面,跳过中间件校验。
  2. Cookie 获取方式兼容性:使用cookies()全局 API 在生产环境可能存在上下文传递问题,不如直接从请求对象获取可靠。
  3. 路由匹配精度:原 matcher 规则虽排除了静态资源,但未明确指定目标路由,可能导致部分请求未触发中间件。

修复方案

1. 强制页面动态渲染

在(main)/page.tsx和(auth)/page.tsx中添加动态渲染配置,确保每次请求都经过中间件:

// src/app/(main)/page.tsx
export const dynamic = 'force-dynamic' // 禁用静态缓存,强制每次请求触发中间件

export default function MainPage() {
  // 页面内容
}
// src/app/(auth)/page.tsx
export const dynamic = 'force-dynamic'

export default function AuthPage() {
  // 页面内容
}

2. 修改中间件代码

优化 Cookie 获取方式,明确路由匹配规则,移除不必要的异步标记:

import { NextRequest, NextResponse } from 'next/server'

const protectedRoutes = ['/']
const publicRoutes = ['/auth']

export function middleware(req: NextRequest) {
  const path = req.nextUrl.pathname
  const isProtectedRoute = protectedRoutes.includes(path)
  const isPublicRoute = publicRoutes.includes(path)

  // 直接从请求对象获取 Cookie,避免全局 API 上下文问题
  const token = req.cookies.get('token')?.value

  // 未认证访问受保护路由,跳转到认证页
  if (isProtectedRoute && !token) {
    const redirectUrl = req.nextUrl.clone()
    redirectUrl.pathname = '/auth'
    return NextResponse.redirect(redirectUrl)
  }

  // 已认证访问公共路由,跳转到首页
  if (isPublicRoute && token) {
    const redirectUrl = req.nextUrl.clone()
    redirectUrl.pathname = '/'
    return NextResponse.redirect(redirectUrl)
  }

  return NextResponse.next()
}

export const config = {
  matcher: [
    // 明确指定需要校验的路由,同时排除静态资源与 API
    '/',
    '/auth',
    '/((?!api|_next/static|_next/image|favicon.ico|.*\\.png$).*)'
  ],
}

设置认证 Cookie 时,需适配生产环境的 HTTPS 环境,确保 Cookie 能被正确传递:

// 示例:在 API 路由中设置 Cookie
import { NextResponse } from 'next/server'

export async function POST(req: Request) {
  // 认证逻辑...
  const token = 'your-auth-token'
  const response = NextResponse.json({ success: true })
  
  response.cookies.set({
    name: 'token',
    value: token,
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production', // 生产环境开启 Secure 属性
    sameSite: 'lax',
    path: '/',
    maxAge: 60 * 60 * 24 * 7 // 一周有效期
  })
  
  return response
}

4. 部署配置验证

确认部署平台(如 Vercel、Netlify)正确识别src/middleware.ts,未忽略该文件的打包与执行。

验证步骤

  1. 生产环境部署后,打开浏览器开发者工具的「Network」面板
  2. 未认证状态下访问/,检查是否触发 307 重定向至/auth
  3. 已认证状态下访问/auth,检查是否触发 307 重定向至/
  4. 查看请求头中的 Cookie 是否正确携带token字段

内容的提问来源于stack exchange,提问作者Felipe Gouvêa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 05:48:25