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
相关产品推荐
相关产品推荐

