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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 13:42:05