基於角色的存取控制
有兩種方法可以使用 Auth.js 將基於角色的存取控制 (RBAC)新增到您的應用程式,具體取決於您選擇的Session 策略。讓我們看看每個策略的範例。
取得角色
首先,將 profile()
回呼新增至提供者的設定,以判斷使用者角色
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", ... }
},
})
],
})
判斷使用者角色是您的責任,您可以新增自己的邏輯,或者如果您的提供者傳回角色,您也可以改用該角色。
持久化角色
持久化角色會根據您使用的Session 策略而有所不同。如果您不知道自己使用的是哪種 Session 策略,那麼您很可能使用的是 JWT(預設策略)。
使用 JWT
當您沒有設定資料庫時,角色會透過使用 jwt()
回呼儲存在 Cookie 中。在登入時,role
屬性會從 user
物件的 profile
回呼中公開。將 user.role
值指派給 token.role
以持久化該值。就是這樣!
如果您也想在用戶端使用該角色,您可以透過 session
回呼公開它。
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
欄新增至使用者模型。
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
回呼公開它。
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。
使用角色
使用者可以透過各自框架的設定檔匯出的授權函數存取目前 Session 中儲存的資訊。此函數會擷取透過設定檔中的 session
和 jwt
回呼公開的資訊。利用此資訊,您可以實作不同的策略和邏輯,根據您的需求顯示 UI。
若要在伺服器端取得資料,您應該從設定檔匯入 auth
函數,並驗證使用者是否具有預期的角色。
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 時,您也可以選擇使用中介軟體,根據使用者的角色重新導向使用者,甚至在轉譯頁面之前。