跳至内容
从 NextAuth.js v4 迁移?请阅读 我们的迁移指南.
指南基于角色的访问控制

基于角色的访问控制

有两种方法可以使用 Auth.js 向您的应用程序添加基于角色的访问控制 (RBAC),具体取决于您选择的会话策略。让我们看看每个策略的示例。

获取角色

首先,向提供者配置添加 profile() 回调,以确定用户角色

./auth.ts
import NextAuth from "next-auth"
import Google from "next-auth/providers/google"
 
export const { handlers, auth } = NextAuth({
  providers: [
    Google({
      profile(profile) {
        return { role: profile.role ?? "user", ... }
      },
    })
  ],
})
💡

确定用户角色是您的责任,您可以添加自己的逻辑,或者如果您的提供者返回角色,您可以直接使用该角色。

持久化角色

持久化角色的方式将取决于您使用的会话策略。如果您不知道使用的是哪种会话策略,那么很可能您使用的是 JWT(默认策略)。

使用 JWT

当您没有配置数据库时,角色将通过使用 jwt() 回调持久化到 cookie 中。在登录时,role 属性将在 user 对象上的 profile 回调中公开。通过将 user.role 值赋给 token.role 来持久化 user.role 值。就这样!

如果您还想在客户端使用角色,则可以通过 session 回调公开它。

./auth.ts
import NextAuth from "next-auth"
import Google from "next-auth/providers/google"
 
export const { handlers, auth } = NextAuth({
  providers: [
    Google({
      profile(profile) {
        return { role: profile.role ?? "user", ... }
      },
    })
  ],
  callbacks: {
    jwt({ token, user }) {
      if(user) token.role = user.role
      return token
    },
    session({ session, token }) {
      session.user.role = token.role
      return session
    }
  }
})

使用此策略,如果您想更新角色,则需要强制用户重新登录。

使用数据库

当您有数据库时,您可以在用户模型上保存用户角色。以下示例展示了如何使用 Prisma 完成此操作,但所有适配器的理念都是一样的。

首先,向用户模型添加 role 列。

/prisma/schema.prisma
model User {
  id            String    @id @default(cuid())
  name          String?
  email         String?   @unique
  emailVerified DateTime?
  image         String?
  role          String?  // New column
  accounts      Account[]
  sessions      Session[]
}

profile() 回调的返回值用于在数据库中创建用户。就这样!您新创建的用户现在将拥有分配的角色。

如果您还想在客户端使用角色,则可以通过 session 回调公开它。

./auth.ts
import NextAuth from "next-auth"
import Google from "next-auth/providers/google"
import prisma from "lib/prisma"
 
export const { handlers, auth } = NextAuth({
  adapter: PrismaAdapter(prisma),
  providers: [
    Google({
      profile(profile) {
        return { role: profile.role ?? "user", ... }
      }
    })
  ],
  callbacks: {
    session({ session, user }) {
      session.user.role = user.role
      return session
    }
  }
})

如何管理更新角色取决于您,您可以通过直接访问数据库或构建角色更新 API 来完成。

使用角色

用户可以通过从相应框架的配置文件中导出的授权函数访问当前会话中存储的信息。此函数检索通过配置文件中的 sessionjwt 回调公开的信息。使用此信息,您可以实现不同的策略和逻辑,以根据您的需求显示 UI。

要在服务器端获取数据,您应该从配置文件中导入 auth 函数,并验证用户是否具有预期的角色。

./app/admin/page.tsx
import { auth } from "@/auth";
 
export default async function Page() {
  const session = await auth();
 
  if (session?.user?.role === "admin") {
    return <p>You are an admin, welcome!</p>;
  }
 
  return <p>You are not authorized to view this page!</p>;
}
💡

当使用 Next.js 和 JWT 时,您也可以使用中间件,根据用户的角色重定向用户,甚至在渲染页面之前。

资源

Auth.js © Balázs Orbán 和团队 -2024