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

Next.js基于角色认证问题:Middleware无法限制跨角色路由访问

解决Next.js Middleware角色路由访问限制问题

原代码仅实现了未登录用户拦截和已登录用户禁止访问Auth页面的逻辑,但完全缺失已登录用户角色与当前访问路由的匹配校验,这是导致跨角色访问的核心原因。以下是修改后的完整实现:

import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { Roles } from './types/role';
import {
  DASHBOARD_PATH,
  FORGOT_PASSWORD,
  LOGIN_PATH,
  RESET_PASSWORD,
  SET_TOKEN,
  WAIT_PATH,
} from './config/constants';

// 角色与对应路由前缀的映射,统一管理权限规则
const ROLE_ROUTE_MAP = {
  [Roles.user1]: '/user1',
  [Roles.user2]: '/user2',
  [Roles.user3]: '/user3',
};

// 未登录用户可访问的白名单路由
const PUBLIC_ROUTES = [
  LOGIN_PATH,
  WAIT_PATH,
  FORGOT_PASSWORD,
  RESET_PASSWORD,
];

export function middleware(request: NextRequest) {
  const token = request.cookies.get(SET_TOKEN)?.value;
  const currentPath = request.nextUrl.pathname;

  // 1. 未登录用户处理:仅允许访问白名单路由,其余跳登录页
  if (!token) {
    const isPublicRoute = PUBLIC_ROUTES.some(route => currentPath.startsWith(route));
    if (!isPublicRoute) {
      return NextResponse.redirect(new URL(LOGIN_PATH, request.url));
    }
    return NextResponse.next();
  }

  // 2. 已登录用户解析角色信息
  const { role } = JSON.parse(token);
  const userAllowedPrefix = ROLE_ROUTE_MAP[role];

  // 3. 禁止已登录用户访问Auth类路由,跳转到对应角色的仪表盘
  const isAuthRoute = PUBLIC_ROUTES.some(route => currentPath.startsWith(route));
  if (isAuthRoute) {
    return NextResponse.redirect(new URL(DASHBOARD_PATH[role], request.url));
  }

  // 4. 核心校验:仅允许访问自身角色对应的路由前缀
  const isAllowedRoute = 
    currentPath.startsWith(userAllowedPrefix) || 
    currentPath.startsWith('/v1'); // 根据实际需求调整/v1路由的权限规则

  if (!isAllowedRoute) {
    // 方案1:跳转到自身角色的仪表盘
    return NextResponse.redirect(new URL(DASHBOARD_PATH[role], request.url));
    // 方案2:返回403禁止访问(更严格的权限控制)
    // return new NextResponse(null, { status: 403 });
  }

  // 所有校验通过,允许访问
  return NextResponse.next();
}

export const config = {
  matcher: [
    '/auth/login',
    '/user1/:path*',
    '/user2/:path*',
    '/auth/wait',
    '/user3/:path*',
    '/v1/:path*',
  ],
};

关键修改说明

  • 统一权限映射:用ROLE_ROUTE_MAP管理角色与路由的对应关系,避免硬编码,后续新增角色只需修改该映射
  • 白名单路由聚合:将未登录可访问路由存入PUBLIC_ROUTES数组,判断逻辑更简洁易维护
  • 新增角色路由校验:已登录用户访问路由时,必须匹配自身角色对应的前缀,否则拦截
  • 逻辑分层:将未登录拦截、Auth路由拦截、角色权限校验拆分为独立模块,代码可读性更高

注意事项

  • 确保Roles枚举的值与ROLE_ROUTE_MAP的键完全匹配(比如Roles.user1的值为'user1')
  • /v1/*的权限规则可根据实际需求调整,比如限制为仅特定角色访问,或改为公共路由
  • 建议对token进行签名校验(如JWT验证),防止伪造token绕过权限控制

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 05:52:55