RBAC 是什麼?從 FB 社團看權限模型
用 Facebook 社團的角色與權限當例子,把 RBAC 這個聽起來很硬的權限模型講成人話。
為什麼#
你有沒有管理過一個 Facebook 社團?如果有,你一定遇過這個時刻:社團從十幾個人變成幾百人,你一個人已經看不完所有貼文,得找幾個朋友幫忙當版主。這時候你會怎麼分工?八成不會把「管理員」密碼直接給對方——你會用 Facebook 內建的角色機制,指派對方當「版主」,讓他能刪貼文、能封鎖搗亂的人,但不能修改社團名稱、不能解散社團,也看不到後台的金流設定。
這個「先分角色、角色再對應到權限」的做法,就是這篇要講的 RBAC(Role-Based Access Control,角色權限存取控制)。它不是什麼新潮框架,而是三十年前就定案的存取控制模型,因為好用到現在還是主流。你在自己的專案裡,遲早會遇到同樣的問題:一開始只有你自己在用系統,後來加了同事、加了客服、加了外部廠商,每個人能做的事不一樣,你總不能為每一個「使用者」單獨寫一套「這個人能不能刪除訂單」的判斷式吧?那樣的程式碼,改一次規則要動十個地方,遲早會有一個地方漏改,變成資安漏洞。
怎麼做#
RBAC 的核心只有三個角色(這裡故意用「角色」這個詞,因為它真的就是這個概念的名字,不是雙關):
使用者(User)——實際登入系統的人,例如你、你的同事、社團裡的某個成員。角色(Role)——一組職稱式的標籤,例如「版主」「管理員」「一般成員」。權限(Permission)——某個角色被允許做的具體動作,例如「刪除貼文」「新增成員」「修改社團設定」。
關鍵在於:使用者不會直接綁定權限,而是先綁定角色,角色再綁定權限。加一個新版主,只要把他標記成「版主」角色就好,不用逐條列出他能做的事——因為「版主能做什麼」這件事,早就在角色定義裡講好了。要調整所有版主的權限?改一個地方(角色定義),不用一個一個使用者去改。
拿 Facebook 社團的三種角色來對照,會更清楚每個角色實際能做什麼、不能做什麼:
| 動作 | 一般成員 | 版主 | 管理員 |
|---|---|---|---|
| 發表貼文 | ✅ | ✅ | ✅ |
| 刪除他人貼文 | ❌ | ✅ | ✅ |
| 封鎖成員 | ❌ | ✅ | ✅ |
| 新增其他版主 | ❌ | ❌ | ✅ |
| 修改社團名稱/解散社團 | ❌ | ❌ | ✅ |
這張表本身就是 RBAC 的全部精神:權限判斷永遠是「這個角色能不能做這件事」,而不是「這個人能不能做這件事」。程式裡對應的邏輯也因此變得非常單純——把使用者查出他的角色,再查角色允許的動作清單,兩者對上了就放行,對不上就擋下來。之後要新增一個「客服」角色、或是幫「版主」多開一個權限,都只是改設定,不用重寫判斷邏輯,也不用擔心漏改到某個使用者。
這套邏輯完全可以搬到你自己的 SaaS 專案裡,只是把「社團」換成「工作區」、把「版主」換成「編輯者」而已。你會有一個資源的概念(例如某篇文章、某張訂單),也會有角色(例如「檢視者」「編輯者」「擁有者」),判斷邏輯永遠是同一句話:「這個角色,對這個資源,能不能做這個動作」。想清楚這三個維度——使用者是誰、角色是什麼、權限對應到哪些資源與動作——比急著挑一個權限管理套件更重要,因為套件只是幫你把這套邏輯寫得更快,概念沒想清楚,套件用得再熟練也是白搭。我自己剛開始接觸這塊的時候,就吃過「先寫程式、後補概念」的虧:權限規則越加越多,最後變成一團誰也不敢動的義大利麵條式判斷式,重構花的時間比當初直接用 RBAC 設計還久。
下一篇我會實際把這套概念用 Casbin 這個函式庫接進 Node.js 專案,讓你看到「角色綁權限」這件事在程式碼裡長什麼樣子,包含 model、policy 兩個檔案要怎麼寫、中介層要怎麼掛。
重點回顧#
RBAC把權限判斷拆成使用者→角色→權限三層,新增使用者只要指定角色,不用重寫規則。- 判斷邏輯只問一句話:「這個角色能不能做這件事」,不是「這個人能不能」。
- 調整權限時改角色定義即可,所有屬於該角色的使用者同時生效,不必逐一修改。
- Facebook 社團的「一般成員/版主/管理員」正是活生生的
RBAC範例,先想清楚有哪些角色、每個角色的邊界在哪,比急著寫程式更重要。
延伸閱讀#
- Casbin 官方文件——下一篇會實際用到的權限函式庫。
- 系列下一篇:〈把 Casbin 接進 Node.js 專案〉,把這篇的概念換成可執行的程式碼。