NextJS+NextAuth中间件未触发求助(v4.18.7/13.1.1)
问题描述
使用next-auth@4.18.7与next@13.1.1,修改项目配置后middleware.ts突然停止工作,完全无法被调用。React端认证功能正常,但中间件无法拦截受保护页面。已尝试将middleware.ts重命名为middleware.page.ts、移动到pages/文件夹,均未解决问题。
相关代码:
middleware.ts
import { withAuth } from "next-auth/middleware"; export default withAuth({ callbacks: { authorized({ req, token }) { const { pathname } = req.nextUrl; console.log(token, pathname); // 该日志从未输出 if (pathname.startsWith("/admin")) { return token?.roleLabel === "ADMIN" || token?.userRole === "admin"; } // `/me`仅要求用户已登录 return !!token; }, }, }); export const config = { matcher: ["/admin/:path*", "/c/:path*", "/me"], };
next.config.js
const { i18n } = require("./next-i18next.config"); const { PHASE_DEVELOPMENT_SERVER } = require("next/constants"); module.exports = (phase) => { let extensions = ['page.tsx', 'page.ts', 'page.jsx', 'page.js', 'api.ts', 'api.js'] if (phase === PHASE_DEVELOPMENT_SERVER) extensions.push('doc.tsx') return { i18n, pageExtensions: extensions, images: { domains: ['domain.com'], }, } };
解决方案
1. 恢复正确的中间件文件名
middleware.ts是Next.js的特殊文件,不需要添加page后缀,必须保持文件名为middleware.ts(或.js),放置在项目根目录(若使用src目录则放在src/根目录),不要放入pages/文件夹。
2. 修正路由匹配规则(适配i18n多语言路由)
由于启用了i18n,访问受保护路径时会自动带上语言前缀(如/en/admin),原matcher规则无法匹配带前缀的路径,导致中间件不触发。修改config.matcher为:
export const config = { matcher: [ // 匹配带语言前缀的受保护路径 '/:lang/admin/:path*', '/:lang/c/:path*', '/:lang/me', // 匹配无语言前缀的默认路径(若项目支持) '/admin/:path*', '/c/:path*', '/me' ], };
若需要更灵活的匹配,可以使用正则表达式覆盖所有非静态资源路径:
export const config = { matcher: [ '/((?!api|_next/static|_next/image|favicon.ico).*)' ], };
3. 确保next-auth使用JWT会话策略
在[...nextauth].ts配置文件中,必须设置session.strategy为"jwt",同时在jwt回调中正确注入roleLabel、userRole等自定义字段:
import NextAuth from "next-auth"; import CredentialsProvider from "next-auth/providers/credentials"; export default NextAuth({ providers: [ // 你的认证提供者配置 CredentialsProvider({ // ... }) ], // 关键:启用JWT策略 session: { strategy: "jwt", }, callbacks: { async jwt({ token, user }) { // 用户登录时将自定义字段注入token if (user) { token.roleLabel = user.roleLabel; token.userRole = user.userRole; } return token; }, async session({ session, token }) { // 将token中的字段同步到session供前端使用 session.user.roleLabel = token.roleLabel; session.user.userRole = token.userRole; return session; }, }, });
4. 清除缓存并重启开发服务器
执行以下命令清除Next.js缓存,避免旧配置残留:
rm -rf .next npm run dev # 或 yarn dev
内容的提问来源于stack exchange,提问作者Gabriel TN
相关产品推荐
相关产品推荐

