您的Next.js中间件匹配器配置可能会跳过您认为它保护的路由

中间件似乎是将Next.js应用的整个部分置于auth之后的最干净的方式,一个文件,一个配置,覆盖了路径下的所有内容。这种信心正是问题所在,因为matcherconfig应该定义"该路径下的所有内容",但它有几个特定的缺口,直到有人点击了一个完全跳过检查的嵌套路由时,这些缺口才会显示出来。

看起来很完整的设置

// middleware.ts

import { NextResponse } from 'next/server';

import { getToken } from 'next-auth/jwt';

export async function middleware(request: NextRequest) {

const token = await getToken({ req: request });

if (!token) {

return NextResponse.redirect(new URL('/login', request.url));

}

return NextResponse.next();

}

export const config = {

matcher: '/dashboard/:path*',

};

上面写着"保护下面的一切"/dashboard,"对于大多数人在开发过程中测试的路线,/dashboard, /dashboard/settings, /dashboard/analytics,它的工作完全符合预期。这种差距在路由组和并行/截取路由约定中表现得尤为明显,它们并不像文件夹结构直观显示的那样映射到URL路径上。

它真正断裂的地方

app/

├── (dashboard)/

│ ├── dashboard/

│ │ └── page.tsx → /dashboard

│ └── settings/

│ └── page.tsx → /settings (NOT /dashboard/settings!)

路由组,即带括号的文件夹,根本不会出现在URL中。一页在app/(dashboard)/settings/page.tsx提供给/settings,不是/dashboard/settings,即使它在视觉上位于代码库中看起来像您的仪表板文件夹的内部。Amatcher: '/dashboard/:path*'模式从不匹配/settings,因为就网址而言,它从来没有下过/dashboard首先。

这正是那种结构上的混乱,很容易从一个依赖于路由组进行布局的文件夹结构中延续下来,我在整个pixelanas.com上的Next.js模板,而不需要重新检查每个受保护页面的实际URL是否仍然在保护它的匹配器模式内,因为文件夹嵌套和URL嵌套已经悄悄地分开了。

第二个更微妙的差距:匹配模式和编码字符

Next.js自己的文档matcherconfig指出,值必须是文字字符串或简单模式,匹配器模式不支持任意的正则表达式特性,编码路径段周围的某些边缘情况或动态段中的异常字符可能无法匹配,从读取模式本身来看并不明显。像这样的路线/dashboard/reports/q1%2F2026(动态段中的编码斜杠)的行为可能不可预测,违背了看起来显然应该覆盖它的模式。

为什么这个没被发现

测试授权路由通常意味着手动点击受保护部分的主页面,即直接嵌套在明显路径下的页面,并确认重定向有效。从技术上讲,页面位于应用程序的同一概念部分,但由于路由组而位于匹配的URL模式之外,或者页面是后来添加的,并且碰巧解析到稍微超出匹配器覆盖范围的URL,所以永远不要根据auth gate进行手动测试,因为没有人会想到检查看起来不需要检查的URL。

解决方法:根据实际解析的URL,而不是文件夹结构,验证匹配器的覆盖范围

不要相信基于你的app/文件夹外观。对照您想要保护的每个页面的实际解析URL进行检查:

export const config = {

matcher: [

'/dashboard/:path*',

'/settings/:path*', // explicitly added once the real URL was checked

'/billing/:path*',

],

};

对于任何真正敏感的东西,更具防御性的模式是完全颠倒逻辑,默认情况下保护所有东西,并明确排除少数公共路径,而不是试图枚举每个受保护的路径,并希望列表随着应用程序的增长而保持完整:

export const config = {

matcher: [

'/((?!login|signup|api/public|_next/static|_next/image|favicon.ico).*)',

],

};

这种模式保护除了明确命名的公共路由之外的所有内容,这意味着路由组下新添加的页面或任何其他位置在默认情况下都受到保护,而不是静静地落在覆盖范围之外,直到有人注意到。

规则

应该根据应用程序的实际解析URL来验证中间件匹配器模式,而不是根据app/文件夹在视觉上是有组织的。路由组、并行路由和截取路由约定都以与文件夹嵌套不匹配的方式影响URL,而这正是看起来安静完整的匹配器模式不匹配的地方。

获取模板: https://www.iissbbs.com

去检查你自己的中间件匹配器,看看它应该保护的每个页面的真实URL,而不是文件夹结构。如果他们中的任何人使用路由组,这是值得今天仔细检查的。放下你在评论中发现的东西。

相关推荐
Chengbei111 小时前
JsOwl|AI 赋能 JS 敏感信息扫描器,AST + 正则、source‑map 源码还原、登录态爬虫输出交互式 HTML 报告
开发语言·javascript·网络·人工智能·爬虫·网络安全·自动化
David猪大卫1 小时前
【C++修炼】string类:string类的模拟实现
c语言·开发语言·数据结构·c++·经验分享·笔记·学习
geovindu1 小时前
rust: Iterator Pattern
开发语言·后端·设计模式·rust·行为模式·迭代器模
SDWAN_Cheap2 小时前
深度解析什么是CDN加速:从原理到实践的技术拆解
开发语言·cdn加速
鬼手点金2 小时前
模型即 Agent:当模型本身成为产品
开发语言·前端·人工智能·python·机器学习
染指11102 小时前
147.Agent-LangGraph归并函数
开发语言·人工智能·python·langchain·agents
Elastic 中国社区官方博客2 小时前
教程:监控 Java 应用
java·开发语言·数据库·elasticsearch·搜索引擎·全文检索
ShineWinsu2 小时前
对于JavaScript:初识JavaScript以及输入输出
java·开发语言·前端·javascript·css·面试·html
小小安于乱2 小时前
linux中java的springboot程序获取IP地址间歇性10秒卡顿问题
java·开发语言