如何在Next.js中间件中通过编程方式获取路由组?
如何在Next.js中间件中通过路由组区分私有/公开路由?
问题背景
Next.js的路由组可用于组织项目文件,但运行时URL中不会包含路由组名称。需要在中间件中区分不同路由组的请求:(admin)组路由需认证+管理员权限,未认证用户重定向至登录页;(marketing)、(blog)组路由无需认证。
现有方案通过维护路由数组判断认证逻辑,存在新增路由易遗漏、数组臃肿的问题,希望利用路由组批量管理认证规则。
实现方案
一、路由组+URL前缀批量匹配(推荐)
路由组本身不影响URL,但可以给不同组的路由设置统一URL前缀,结合中间件的正则匹配实现批量认证:
文件结构组织
将不同路由组的文件按前缀目录存放,既利用路由组整理结构,又通过URL前缀区分权限:app/ (admin)/ admin/ dashboard/ page.tsx users/ page.tsx layout.tsx (marketing)/ marketing/ about/ page.tsx contact/ page.tsx (blog)/ blog/ [slug]/ page.tsx layout.tsx对应的URL:
- (admin)组:
/admin/dashboard、/admin/users - (marketing)组:
/marketing/about、/marketing/contact - (blog)组:
/blog/xxx
- (admin)组:
中间件实现
通过正则匹配URL前缀,批量处理不同组的认证逻辑:import { NextRequest, NextResponse } from 'next/server'; async function getUserFromSession(cookies: any) { // 你的会话验证逻辑,比如从cookie中获取用户信息 return null; } export async function middleware(request: NextRequest) { const pathname = request.nextUrl.pathname; const user = await getUserFromSession(request.cookies); // 处理(admin)组路由:需登录+管理员权限 if (/^\/admin\/.*$/.test(pathname)) { if (!user) { return NextResponse.redirect(new URL('/sign-in', request.url)); } if (user.role !== 'admin') { return NextResponse.redirect(new URL('/', request.url)); } } // (marketing)、(blog)组路由无需处理,直接放行 return NextResponse.next(); } // 可选:配置匹配器缩小中间件作用范围,提升性能 export const config = { matcher: ['/admin/:path*', '/marketing/:path*', '/blog/:path*'], };
二、路由映射文件(替代方案)
若不想修改URL结构,可创建统一的路由映射文件,维护路由组与对应路径的关系,避免手动维护庞大数组:
创建路由映射文件
在项目根目录创建route-groups.json:{ "admin": ["/dashboard", "/users", "/settings"], "public": ["/about", "/contact", "/blog", "/blog/[slug]"] }中间件中读取映射文件
import { NextRequest, NextResponse } from 'next/server'; import routeGroups from '../route-groups.json'; async function getUserFromSession(cookies: any) { // 你的会话验证逻辑 return null; } export async function middleware(request: NextRequest) { const pathname = request.nextUrl.pathname; const user = await getUserFromSession(request.cookies); // 检查是否属于admin路由组 if (routeGroups.admin.includes(pathname)) { if (!user) { return NextResponse.redirect(new URL('/sign-in', request.url)); } if (user.role !== 'admin') { return NextResponse.redirect(new URL('/', request.url)); } } return NextResponse.next(); }后续新增路由只需更新
route-groups.json,无需修改中间件代码。
注意事项
- Next.js运行时无法直接获取路由组的目录信息,因此无法直接通过路由组名称判断请求所属组,需通过URL前缀或映射文件间接实现批量管理。
- 使用匹配器(
config.matcher)可缩小中间件的作用范围,减少不必要的逻辑执行,提升性能。
内容的提问来源于stack exchange,提问作者René Link
相关产品推荐
相关产品推荐

