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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 17:25:19