Next.js14中基于NextAuth实现多角色路由权限控制的方法咨询
Next.js 14 + Auth.js 多角色路由权限控制实现方案
要实现多角色对应多路由的权限控制,核心思路是在 middleware.ts 中定义路由-角色映射规则,然后在请求拦截时验证用户角色是否符合当前路由的访问权限。以下是具体实现步骤和代码示例:
1. 确保角色信息存入Session
首先需要在Auth.js的配置中,把用户角色信息存入Session,这样Middleware才能获取到角色数据。在你的auth.ts(或auth.js)配置文件中添加回调:
import NextAuth from "next-auth"; import Credentials from "next-auth/providers/credentials"; // 根据实际情况引入数据库操作工具 import { db } from "@/lib/db"; export const { auth, handlers, signIn, signOut } = NextAuth({ providers: [ Credentials({ credentials: { email: { label: "Email", type: "email" }, password: { label: "Password", type: "password" } }, async authorize(credentials) { // 从数据库查询用户信息,需包含role字段 const user = await db.user.findUnique({ where: { email: credentials?.email } }); if (!user) return null; // 此处添加密码验证逻辑(比如bcrypt比对) return { id: user.id, email: user.email, role: user.role }; } }) ], callbacks: { async jwt({ token, user }) { // 登录时将角色写入JWT if (user) token.role = user.role; return token; }, async session({ session, token }) { // 将角色从JWT同步到Session if (session.user) session.user.role = token.role as string; return session; } } });
2. 编写Middleware实现权限校验
在项目根目录创建middleware.ts,通过路由规则匹配和角色校验实现权限控制:
import { auth } from '@/auth'; import { NextResponse } from 'next/server'; // 定义路由权限规则:路径正则表达式 + 允许访问的角色数组 const routeAccessRules = [ { path: /^\/normal$/, allowedRoles: ['user'] }, // 仅user角色可访问/normal { path: /^\/admin(\/.*)?$/, allowedRoles: ['admin'] }, // admin角色可访问/admin及所有子路由 { path: /^\/dashboard$/, allowedRoles: ['user'] } // 仅user角色可访问/dashboard ]; // 无需权限校验的公共路由 const publicRoutes = ['/', '/login', '/register']; export default auth((req) => { const { nextUrl } = req; const currentPath = nextUrl.pathname; // 公共路由直接放行 if (publicRoutes.includes(currentPath)) { return NextResponse.next(); } const session = req.auth; // 未登录用户访问私有路由,重定向到登录页 if (!session) { return NextResponse.redirect(new URL('/login', nextUrl)); } const userRole = session.user?.role as string; // 匹配当前路径对应的权限规则 const matchedRule = routeAccessRules.find(rule => rule.path.test(currentPath)); if (matchedRule) { // 检查用户角色是否在允许列表中 if (!matchedRule.allowedRoles.includes(userRole)) { // 无权限时重定向到403页面,也可直接返回403响应 return NextResponse.redirect(new URL('/403', nextUrl)); // 或者返回403状态:return new NextResponse('Forbidden', { status: 403 }) } } // 所有校验通过,放行请求 return NextResponse.next(); }); // 指定Middleware生效的路径(仅对需要校验的路由生效,优化性能) export const config = { matcher: ['/normal', '/admin/:path*', '/dashboard'] };
关键注意事项
- 路由匹配规则:使用正则表达式可以灵活处理精确路由和子路由,比如
/^\/admin(\/.*)?$/会匹配/admin、/admin/users、/admin/settings等所有admin子路由。 - 无权限处理:根据业务需求选择重定向到403页面或直接返回403状态码。
- 公共路由扩展:把不需要校验的路由(如静态资源、公开API)加入
publicRoutes列表,避免不必要的校验。 - 角色字段正确性:确保从数据库查询或登录提供商返回的用户对象中包含
role字段,并且在Auth.js的回调中正确同步到Session。
内容的提问来源于stack exchange,提问作者Carlos Terrazas
相关产品推荐
相关产品推荐

