NextJS子应用Zone中Middleware函数未触发问题求助
问题分析与解决方案
核心问题排查
你的子应用Middleware未触发,主要是以下几个关键错误导致:
自定义Middleware被覆盖
你同时导出了next-auth/middleware作为默认导出,这会直接覆盖你自己写的middleware函数——Next.js Middleware只会执行默认导出的函数,所以你的自定义逻辑根本没被调用。路径匹配规则错误
子应用部署在/subapp路径下,但Nginx代理时如果没有重写路径,子应用内部收到的请求路径会带/subapp前缀吗?不对,正确的代理应该把/subapp/*重写为/*传给子应用,所以子应用内部的路由是基于自身根路径的,你的matcher里写/subapp/play完全不匹配子应用内部的路径,自然不会触发Middleware。配置项放错位置
pages.signIn是Next-Auth核心配置的选项,不是Middleware的config对象属性,放这里完全无效。
分步修复方案
1. 修正子应用Middleware代码
去掉Next-Auth默认导出,保留自定义逻辑,同时调整匹配路径为子应用内部的相对路径:
import { NextRequest, NextResponse } from 'next/server'; export async function middleware(req: NextRequest) { console.log("TEST"); // 现在应该能正常打印 const session = req.cookies.get('next-auth.session-token'); if (session) { return NextResponse.next(); } else { // 重定向到主应用的登录页,注意用origin拼接路径 return NextResponse.redirect(new URL('/signin', req.nextUrl.origin)); } } export const config = { matcher: [ "/", // 对应外部访问的 /subapp "/play", // 对应外部访问的 /subapp/play "/api/:path*" // 对应外部访问的 /subapp/api/* ], };
2. 调整Nginx代理配置
必须确保代理子应用时重写路径,去掉/subapp前缀,让子应用收到的是自身根路径的请求:
server { listen 3000; server_name localhost; # 主应用代理 location / { proxy_pass http://main-app-container:3000; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; } # 子应用代理:关键是rewrite规则 location /subapp { proxy_pass http://subapp-container:3000; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; # 去掉/subapp前缀,传给子应用的是真实路径 rewrite ^/subapp(.*)$ $1 break; } }
3. 确认主应用Next-Auth的Cookie配置
确保主应用生成的认证Cookie路径为/,这样子应用能跨路径读取:
在主应用的[...nextauth].ts中添加:
export default NextAuth({ // ...其他认证配置 cookies: { sessionToken: { name: "next-auth.session-token", path: "/", // 关键:Cookie作用域设为根路径 httpOnly: true, sameSite: "lax", secure: process.env.NODE_ENV === "production", }, }, });
可选:用Next-Auth官方Middleware简化逻辑
如果不想自己写校验逻辑,可以直接用Next-Auth的官方Middleware,只需调整匹配路径和登录页配置:
// 子应用middleware.ts export { default } from "next-auth/middleware"; export const config = { matcher: ["/", "/play", "/api/:path*"], };
然后在子应用的[...nextauth].ts中指定登录页:
export default NextAuth({ // ...和主应用一致的认证提供者配置 pages: { signIn: "/signin", // 自动重定向到主应用的登录页 }, cookies: { sessionToken: { path: "/", }, }, });
内容的提问来源于stack exchange,提问作者DRE
相关产品推荐
相关产品推荐

