授權是我們應用程式中決定使用者可以在何種資源上執行哪些操作的過程,這是每個應用程式的重要要求。實施基於角色的存取控制 (RBAC) 是一個簡單的方法來管理和控制我們應用程式中的授權。
在這篇文章中,我們將討論如何在 Next.js 應用程式中以安全和可擴展的方式添加 RBAC 授權的過程。
我們將從在 Next.js 中設置一個基本的待辦事項應用程式開始,並實施 JWT 用於使用者身份驗證。接下來,我們將使用Permit.io 配置 RBAC 政策,同步我們的使用者,並將使用者的角色升級為具有全部權限的管理員。
在本教程結束時,您將清楚地了解如何使用 RBAC 保護 Next.js 應用程式,讓您完全控制每個使用者根據其角色可以訪問的內容。
讓我們開始吧!
為了開始,讓我們創建一個新的 Next.js 專案。為了節省時間(假設您理解 Next.js 的基本概念),我們已經設置了一個啟動專案,您將找到我們在本教程中將使用的簡單待辦事項應用程式。
確保您的電腦上已安裝 Node.js 和 npm。您可以從官方Node.js 網站下載它們。
打開終端窗口,使用以下命令創建一個新的 Next.js 專案:
git clone https://github.com/Arindam200/Permit-RBAC
這將複製一個具有默認設置的 Next.js 專案,其中包含我們將在本教程中使用的啟動代碼。
cd rbac-permit-starter-next.js
npm install
現在我們已成功在本地設置了 Next.js 專案,我們可以繼續實施基本的 RBAC 模型。
在開始授權之前,我們需要驗證使用者身份。
身份驗證階段驗證並為每個使用者提供唯一的身份,這有助於區分一個使用者與另一個使用者。授權限制使用者只能在應用程式內執行他們被授權執行的操作。
為了保持我們的應用程式簡單,我們正在使用兩個具有管理員和一般使用者權限的虛擬 JWT。相同的方法將適用於與任何提供 JWT 的身份驗證提供者的實施,例如 Clerk、Auth0 或 Kinde。
虛擬使用者詳細信息如下:
在您的代碼編輯器中,導航到檔案 src > data > sampleData.js 裡的代碼:
const sampleData = [
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwibmFtZSI6IlByb2plY3QgQWRtaW4iLCJlbWFpbCI6ImFkbWluQGdtYWlsLmNvbSJ9.KtQpee_bZF_Sx0t87trx8-ljuE3SwJ7SZYeYzZO-694",
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwibmFtZSI6IlByb2plY3QgVXNlciIsImVtYWlsIjoidXNlckBnbWFpbC5jb20ifQ.FVG2dcFVsOy1cmzImHqtbeJ0mnT1h4aCSN7aSPq9Xew",
];
export default sampleData;
這包含了上面寫的憑據的兩個使用者的 JWT。我們將解碼這些 JWT 以獲取使用者信息。
開發人員經常使用以下具體的條件語句來強制執行 RBAC 規則。
在這個例子中,我們有一個包含 ID 和角色屬性的使用者物件。
deleteUser 函數檢查當前使用者的角色是否為 'admin',然後才允許他刪除使用者。
updatePost 函數檢查使用者角色是否已被更新。
使用具體的 if
語句硬編碼授權規則會產生幾個問題:
if
語句變得複雜且難以維護,這使得代碼容易出錯且不易閱讀。在本教程中,我們將使用Permit.io 實施 RBAC - 一個授權即服務提供者。Permit.io 通過提供更集中、靈活和可擴展的權限管理方法,解決了硬編碼授權的缺點。
要開始配置權限,請登錄 app.permit.io。接下來,我們將為這個專案創建一個新的工作區。
按照以下步驟操作:
接下來,我們需要創建一個資源。資源是我們應用程式中需要保護或管理訪問的任何元素。例如,在這個應用程式中,Todo 是一個代表我們需要管理和保護的任務的資源。
讓我們創建一個名為 Todo 的資源。
接下來,我們將創建一個角色。角色是一種簡單的方式,可以將權限分組並分配給使用者或其他實體。
接下來,我們將轉到“政策編輯器”部分並設置政策。在設置政策之前,讓我們討論一下這些行動:
我們需要更新我們的政策,以便管理員有權執行所有動作,而使用者僅能執行閱讀和更新動作。
要創建這個政策,請轉到政策編輯器,按下面顯示的方式勾選所有複選框,然後保存更改。
就這樣。我們已成功設置了基於角色的存取控制 (RBAC) 模型,可以在我們的應用程式中使用。
現在我們已經創建了 RBAC 配置,讓我們將虛擬使用者添加到我們的 Permit.io 目錄。由於我們使用的是虛擬 JWT,我們將手動將使用者添加到 Permit 目錄。如果您有身份驗證提供者,則可以利用 syncUser
API 將所有現有使用者導入 Permit。
開始操作:
現在我們已在 Permit 中創建了一些使用者,我們準備開始編碼。
讓我們開始添加環境變量:
設定 > API 密鑰 > 開發密鑰
PERMIT_TOKEN=”複製的 API 密鑰”
現在讓我們將應用程式與 Permit.io 連接,以實施我們已設置的政策。
為此,我們將創建一個網關,使用 API 令牌和政策決策點 (PDP) 端點初始化 Permit.io 客戶端。
這種設置允許應用程式根據預定的存取控制規則執行授權檢查。
src > lib > permitProvider.js
import { Permit } from 'permitio';
const permit = new Permit({
// 用於與 Permit.io API 認證的令牌
token: process.env.NEXT_PUBLIC_PERMIT_TOKEN,
// Permit.io 用於評估政策的政策決策點 (PDP) URL
pdp: "https://cloudpdp.api.permit.io",
});
export default permit;
現在我們已經創建了兩個使用者,是時候利用現有政策來測試我們的基於角色的存取控制 (RBAC) 模型的運作。
在我們繼續之前,讓我們討論一下檢查是如何運作以授予或限制對授權個體的存取。
讓我們了解一下我們將如何在應用程式中實施授權:
user_id
和操作名稱發送到後端 API。現在我們已經將應用程式與 Permit.io 連接,是時候看看 Permit.io 如何管理資源。
src > api > check-permission > route.js
import permit from "@/lib/permitProvider";
export async function GET(req) {
const { searchParams } = new URL(req.url)
const id = searchParams.get('id');
const operation = searchParams.get('operation')
try {
const permitted = await permit.check(String(id), String(operation), {
type: 'TodoTasks',
tenant: 'todo-tenant',
});
if (permitted) {
return Response.json({
success: true,
message: "被允許"
}, { status: 200 })
}
} catch (err) {
console.error("檢查權限時出錯:", err);
}
return Response.json({
success: false,
message: "不被允許"
}, { status: 403 })
}
在上述代碼中,我們提取查詢參數,使用 Permit.io 檢查權限並返回結果。
以下是逐步分析:
GET
函數由對該 API 路由的 HTTP GET 請求觸發。id
和 operation
參數。permit.check()
方法,在 todo-tenant
中檢查是否由 id
標識的使用者有權執行指定的操作(例如,創建、更新、刪除)在 TodoTasks
資源上。現在來看看這個集中化的函數如何進行 API 調用:
const checkPermission = async (operation) => {
const response = await fetch(`/api/check-permission?id=${identifier}&operation=${operation}`);
const data = await response.json();
return data.success;
};
它通過所需的參數 ID 和操作來響應我們設計的 API 路由。
我們有我們的 Todo 資源,根據其政策,具有“管理員”角色的個體可以執行所有五個動作:讀取、創建、編輯、更新和刪除。而“使用者”角色的僅能執行讀取和更新操作。
創建:確認個體是否具有 "編輯" 權限的函數,並使用新值更新指定的待辦事項。
const handleSaveEdit = async () => {
if (!await checkPermission("edit")) {
alert("您沒有編輯待辦事項的權限。");
return;
}
const updatedTodos = todos.map((todo, i) =>
i === editingIndex
? { ...todo, content: editingContent, deadline: editingDeadline, priority: editingPriority }
: todo
);
setTodos(updatedTodos);
setEditingIndex(null);
setEditingContent("");
setEditingDeadline("");
setEditingPriority("low");
};
編輯:確認個體是否具有 "編輯" 權限以更新指定的待辦事項。
const handleSaveEdit = async () => {
if (!await checkPermission("edit")) {
alert("您沒有編輯待辦事項的權限。");
return;
}
const updatedTodos = todos.map((todo, index) =>
index === editingIndex
? { ...todo, content: editingContent, deadline: editingDeadline, priority: editingPriority }
: todo
);
setTodos(updatedTodos);
setEditingIndex(null);
setEditingContent("");
setEditingDeadline("");
setEditingPriority("low");
};
更新:確認個體是否具有 "更新" 權限,切換指定待辦事項的 "完成" 狀態。
const handleToggleDone = async (index) => {
if (!await checkPermission("update")) {
alert("您沒有更新待辦事項的權限。");
return;
}
const updatedTodos = todos.map((todo, i) =>
i === index ? { ...todo, done: !todo.done } : todo
);
setTodos(updatedTodos);
};
刪除:確認個體是否具有 "刪除" 權限,並從列表中移除指定的待辦事項。
const handleDeleteTodo = async (index) => {
if (!await checkPermission("delete")) {
alert("您沒有刪除待辦事項的權限。");
return;
}
const updatedTodos = todos.filter((_, i) => i !== index);
setTodos(updatedTodos);
};
我們已添加所有必要的操作來根據定義的角色限制個體的行為,並定義函數以創建、編輯、更新和刪除我們的 Todo 應用程式中的項目。
至此,我們的簡單 Todo 應用程式與 Next.js 和 Permit 完成了 🥳。
您可以通過運行以下命令啟動應用程式:
npm run dev
這將使我們的 Next.js 應用程式在 http://localhost:3000 上運行。
在這個演示中,我們將展示我們的使用者如何只能讀取待辦事項但無法編輯或刪除它們:
要將使用者的角色從使用者改為管理員,請導航到 Permit.io 儀表板,並根據如下所示更新使用者的角色分配:
更新角色為管理員之後,該使用者現在在應用程式中擁有全部權限。作為管理員,該使用者可以:
以下視頻演示了管理員角色的增強功能:
這就是如何輕鬆地在任何應用程式中實施 RBAC 政策,也就是使用permit.io。
我們也可以看到在 Permit.io 儀表板的審核日誌部分請求的跟蹤,如下所示:
在本教程中,我們探討了如何設置和配置 Next.js 應用程式中的 RBAC,以根據使用者角色控制訪問。
現在您已將 RBAC 實施到您的應用程式中,您可以利用它來提高應用程式的安全性,針對應用程式中的真實用例進行應用。
如果您想要比用戶角色更細粒度的控制,但又需要用戶詳細身份,該怎麼辦?
為了獲得這些及更多,我們建議您繼續閱讀我們的學習材料,例如RBAC 與 ABAC 之間的區別以及使用 Permit.io 將 ABAC 添加到您的應用程序。
想要了解更多關於實施授權的信息?有問題嗎?隨時通過我們的Slack 社區與我們聯繫。
原文出處:https://dev.to/studio1hq/how-to-add-rbac-authorization-in-nextjs-16m3