如何将next-intl中间件与Next.js 15现有认证中间件整合?
解决Next.js 15 App Router中next-intl与认证中间件结合的问题
核心问题分析
现有认证中间件直接判断pathname是否为/einloggen,但next-intl会为路由添加locale前缀(比如/de/einloggen或/en/login),导致认证逻辑无法匹配;同时两个中间件的执行顺序和路由解析逻辑需要整合到同一个middleware中,不能分开运行。
具体实现步骤
1. 合并中间件逻辑
将next-intl的路由处理逻辑和认证逻辑整合到同一个src/middleware.ts文件中。
2. 完整整合代码
import { NextRequest, NextResponse } from "next/server"; import { getSession } from "@/lib/auth/iron-session"; import createMiddleware from "next-intl/middleware"; // 初始化next-intl中间件,配置支持的语言和默认语言 const intlMiddleware = createMiddleware({ locales: ["de", "en"], // 根据实际业务调整语言列表 defaultLocale: "de" }); export async function middleware(request: NextRequest) { // 先执行next-intl的路由本地化处理 const intlResponse = intlMiddleware(request); // 提取不带locale前缀的路径,比如从/de/einloggen得到/einloggen const localePrefixPattern = /^\/([a-z]{2})\//; const cleanPathname = request.nextUrl.pathname.replace(localePrefixPattern, "/"); // 执行原有认证逻辑 const session = await getSession(); const isLoggedIn = session.isLoggedIn; // 调整认证判断逻辑,适配本地化路径 if (!isLoggedIn && cleanPathname !== "/einloggen") { // 重定向到对应语言的登录页 const loginUrl = new URL(`/${request.nextUrl.locale || "de"}/einloggen`, request.url); return NextResponse.redirect(loginUrl); } if (isLoggedIn && cleanPathname === "/einloggen") { // 重定向到对应语言的首页 const homeUrl = new URL(`/${request.nextUrl.locale || "de"}`, request.url); return NextResponse.redirect(homeUrl); } // 认证逻辑无重定向时,返回next-intl处理后的响应 return intlResponse; } export const config = { // 匹配所有需处理路由,排除next内部资源和静态文件 matcher: ["/((?!_next|favicon.ico|assets).*)"] };
3. 关键调整说明
- 整合中间件执行顺序:先让next-intl完成路由本地化解析,再基于清理后的路径执行认证判断,避免locale前缀干扰逻辑。
- 路径清理:通过正则移除locale前缀,让原有认证逻辑无需修改即可适配多语言路由。
- 本地化重定向:重定向时自动带上当前语言前缀,避免触发next-intl的二次路由修正。
- 兼容matcher配置:保持原有排除规则,确保静态资源和next内部路径不被中间件处理。
4. 多语言登录页适配(可选)
如果不同语言对应不同登录页路径(比如德语/einloggen、英语/login),可修改认证逻辑如下:
// 定义各语言对应的登录页路径 const loginPaths = { de: "/einloggen", en: "/login" }; const currentLoginPath = loginPaths[request.nextUrl.locale as keyof typeof loginPaths] || "/einloggen"; // 替换原有判断逻辑中的"/einloggen"为currentLoginPath if (!isLoggedIn && cleanPathname !== currentLoginPath) { const loginUrl = new URL(`/${request.nextUrl.locale || "de"}${currentLoginPath}`, request.url); return NextResponse.redirect(loginUrl); } if (isLoggedIn && cleanPathname === currentLoginPath) { const homeUrl = new URL(`/${request.nextUrl.locale || "de"}`, request.url); return NextResponse.redirect(homeUrl); }
内容的提问来源于stack exchange,提问作者Assad Rajab
相关产品推荐
相关产品推荐

