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

如何在Next.js中间件中匹配动态路由并实现路由保护

问题原因

你当前代码用protectedRoutes.includes(path)做路径匹配,这是严格的字符串全等判断。/dashboard/sam32和数组里的/dashboard/:param*是完全不同的字符串,所以永远匹配失败,导致动态路由不会被标记为受保护路由。

解决方案

要匹配动态路由,需要用模式匹配逻辑(比如正则表达式)替代简单的字符串包含判断。下面是修改后的完整代码:

import { auth } from "@/auth"
import { NextRequest, NextResponse } from 'next/server'

// 1. 定义受保护路由的匹配模式(支持动态路由)
const protectedRoutePatterns = [
  /^\/dashboard\/[^/]+$/, // 匹配 /dashboard/xxx 这类单级动态路由
  /^\/message\/.*$/       // 匹配 /message/ 下的所有子路由
]
const publicRoutes = ['/login', '/signup', '/']

export default async function middleware(req: NextRequest) {
  const path = req.nextUrl.pathname

  // 2. 检查当前路径是否匹配受保护路由模式
  const isProtectedRoute = protectedRoutePatterns.some(pattern => pattern.test(path))
  const isPublicRoute = publicRoutes.includes(path)

  const session = await auth();

  // 3. 未登录用户访问受保护路由,重定向到登录页
  if (isProtectedRoute && !session) {
    return NextResponse.redirect(new URL('/login', req.nextUrl))
  }

  // 4. 已登录用户访问公共路由(除了首页),重定向到仪表盘
  if (isPublicRoute && session?.user && path !== '/') {
    return NextResponse.redirect(new URL('/dashboard', req.nextUrl))
  }

  return NextResponse.next()
}

export const config = {
  matcher: ['/((?!api|_next/static|_next/image|.*\\.png$).*)'],
}
关键修改点
  • 将受保护路由从字符串数组改为正则表达式数组,精准匹配动态路由格式:
    • /^\/dashboard\/[^/]+$/ 匹配/dashboard/后跟任意非斜杠字符的路径(如/dashboard/sam32)
    • /^\/message\/.*$/ 匹配/message/下的所有子路由(包括/message/123、/message/inbox等)
  • 用Array.some()结合正则的test()方法判断路径是否符合受保护模式
  • 修正公共路由重定向条件:原代码的!req.nextUrl.pathname.startsWith('/')永远为false,改成path !== '/',避免已登录用户访问首页时被强制重定向
其他可选方案

如果不想写正则,也可以用路径前缀判断(适合简单场景):

const isProtectedRoute = path.startsWith('/dashboard/') || path.startsWith('/message/')

这种方式更简洁,但要注意如果存在/dashboard根路径(不带动态参数),需要单独排除或调整判断逻辑。

内容的提问来源于stack exchange,提问作者SamOlisa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 04:07:37