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

如何在Next.js中间件中通过编程方式获取路由组?

如何在Next.js中间件中通过路由组区分私有/公开路由?

问题背景

Next.js的路由组可用于组织项目文件,但运行时URL中不会包含路由组名称。需要在中间件中区分不同路由组的请求:(admin)组路由需认证+管理员权限,未认证用户重定向至登录页;(marketing)、(blog)组路由无需认证。

现有方案通过维护路由数组判断认证逻辑,存在新增路由易遗漏、数组臃肿的问题,希望利用路由组批量管理认证规则。

实现方案

一、路由组+URL前缀批量匹配(推荐)

路由组本身不影响URL,但可以给不同组的路由设置统一URL前缀,结合中间件的正则匹配实现批量认证:

  1. 文件结构组织
    将不同路由组的文件按前缀目录存放,既利用路由组整理结构,又通过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
  2. 中间件实现
    通过正则匹配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结构,可创建统一的路由映射文件,维护路由组与对应路径的关系,避免手动维护庞大数组:

  1. 创建路由映射文件
    在项目根目录创建route-groups.json:

    {
      "admin": ["/dashboard", "/users", "/settings"],
      "public": ["/about", "/contact", "/blog", "/blog/[slug]"]
    }
    
  2. 中间件中读取映射文件

    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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 00:16:03