Next.js中间件动态受保护路由失效,寻求解决方案
解决Next.js动态路由未被中间件正确保护的问题
问题原因
你当前的代码通过protectedRoutes.includes(request.nextUrl.pathname)判断是否为受保护路由,但动态路由的实际请求路径(如/profile/123)和定义的/profile/[id]格式完全不同,导致includes无法匹配到动态路由,未认证用户因此能直接访问。
解决方案
使用URLPattern API(Next.js原生支持)来匹配动态路由,它能正确识别[id]这类动态参数格式,匹配实际请求路径。
修改后的middleware.ts代码如下:
import { NextRequest, NextResponse } from 'next/server'; import { protectedRoutes, authRoutes } from './routes'; // 为每个受保护路由创建URLPattern实例 const protectedRoutePatterns = protectedRoutes.map(route => new URLPattern({ pathname: route })); export function middleware(request: NextRequest) { const currentUser = request.cookies.get("currentUser")?.value; // 检查当前请求路径是否匹配任意受保护路由 const isProtectedRoute = protectedRoutePatterns.some(pattern => pattern.test(request.nextUrl)); if ( isProtectedRoute && (!currentUser || Date.now() > JSON.parse(currentUser).expiredAt) ) { request.cookies.delete("currentUser"); const response = NextResponse.redirect(new URL("/login", request.url)); response.cookies.delete("currentUser"); return response; } if (authRoutes.includes(request.nextUrl.pathname) && currentUser) { return NextResponse.redirect(new URL("/profile", request.url)); } } // 确保所有路径都经过中间件处理 export const config = { matcher: '/:path*', };
替代方案:正则表达式匹配
如果你更倾向于用正则,也可以将动态路由格式转换为正则表达式来匹配:
import { NextRequest, NextResponse } from 'next/server'; import { protectedRoutes, authRoutes } from './routes'; // 将动态路由转换为正则(把[id]替换为匹配任意非斜杠字符的规则) const protectedRouteRegexes = protectedRoutes.map(route => { const regexPath = route.replace(/\[.*?\]/g, '[^/]+'); return new RegExp(`^${regexPath}$`); }); export function middleware(request: NextRequest) { const currentUser = request.cookies.get("currentUser")?.value; const isProtectedRoute = protectedRouteRegexes.some(regex => regex.test(request.nextUrl.pathname)); if ( isProtectedRoute && (!currentUser || Date.now() > JSON.parse(currentUser).expiredAt) ) { request.cookies.delete("currentUser"); const response = NextResponse.redirect(new URL("/login", request.url)); response.cookies.delete("currentUser"); return response; } if (authRoutes.includes(request.nextUrl.pathname) && currentUser) { return NextResponse.redirect(new URL("/profile", request.url)); } } export const config = { matcher: '/:path*', };
关键注意点
- 添加
export const config = { matcher: '/:path*' };可以确保所有请求路径都经过中间件处理,避免遗漏路由。 - URLPattern是标准Web API,兼容性更好,推荐优先使用。
内容的提问来源于stack exchange,提问作者softwarekeveloper
相关产品推荐
相关产品推荐

