如何為你的 App 加入角色式存取控制(RBAC)
要加入角色式存取控制,首先為每位用戶指派一個或多個角色(例如管理員、編輯、檢視者),定義每個角色可以執行嘅操作,然後喺伺服器上為每個請求檢查呢啲權限,唔好只係隱藏按鈕。另外亦要檢查被存取嘅記錄是否屬於該用戶嘅帳戶或團隊。一開始先喺資料庫設定幾個固定角色,並透過直接嘗試存取其他用戶嘅資料來測試。
驗證 vs 授權
兩個經常被混淆嘅詞語:
- 驗證係「你係邊個?」,即登入。參閱如何為你的 App 加入登入。
- 授權係「你可以做乜嘢?」,即已登入嘅用戶可以存取邊啲頁面、記錄同操作。
RBAC 係最常見嘅授權方法。當中有一點好重要:截至 2026 年 9 月,**Broken Access Control(存取控制失效)**喺 OWASP Top 10:2025 排第一位,而 OWASP Top 10 係廣泛採用、列出最嚴重網頁應用程式安全風險嘅清單。常見問題包括用戶改動網址中嘅 ID 就可以讀取其他用戶嘅記錄,或者普通用戶可以呼叫只限管理員使用嘅 API 路由。
選擇模型
| 模型 | 運作方式 | 適合 | 取捨 |
|---|---|---|---|
| 單一角色欄位 | users.role = admin / member | 只有兩至三個角色嘅小型 App | 當人哋需要喺唔同地方擁有唔同角色時,會變得混亂 |
| 角色加權限 | 角色對應到具名權限(例如 invoices.approve);程式碼檢查權限 | 規則會不斷增加嘅 App | 要多幾張表;要維護權限清單 |
| 每個團隊(多租戶)角色 | 一張成員表:用戶 + 機構 + 角色 | 用戶屬於團隊或工作區嘅 SaaS | 每個查詢都必須限定喺該機構範圍內 |
| 以屬性或關係為本 | 根據記錄屬性(「作者可以編輯自己嘅文章」)或關係(「已與你分享」)定規則 | 文件、分享同複雜流程 | 較難理解;可以考慮使用專門嘅函式庫或服務 |
| 驗證供應商角色 | 你嘅登入供應商儲存角色或機構成員資格 | 已經使用託管驗證服務嘅 App | 綁定該供應商;仍然要喺你嘅伺服器上執行 |
實際上,大部分 App 會結合兩樣嘢:角色決定某人可以做邊類操作,擁有權決定佢可以對邊啲記錄操作。「編輯可以編輯文章」係角色規則;「……屬於自己工作區嘅文章」則係擁有權規則。兩者你都需要。
開始時可以簡單啲。管理員、成員同檢視者已經足夠應付好多 App。以後再拆分角色,比起要整理十個冇人明白嘅角色,容易得多。
寫程式前先設計角色
先用白話寫一張權限表,佢既係 AI 嘅規格,亦係你嘅測試計劃:
| 操作 | 擁有者 | 管理員 | 成員 | 檢視者 |
|---|---|---|---|---|
| 查看團隊內嘅專案 | ✓ | ✓ | ✓ | ✓ |
| 建立及編輯專案 | ✓ | ✓ | ✓ | |
| 刪除專案 | ✓ | ✓ | ||
| 邀請及移除成員 | ✓ | ✓ | ||
| 更改角色 | ✓ | |||
| 帳單 | ✓ |
邊緣情況亦要決定:最後一位擁有者可唔可以離開?管理員可唔可以移除擁有者?被移除嘅用戶會見到乜嘢?
逐步做法
1. 先確保登入運作正常
RBAC 建基於驗證之上。伺服器必須可靠地知道每個請求係由邊位用戶發出,並且要根據 session 或已驗證嘅 token 判斷,而唔可以根據瀏覽器喺請求內文傳送嘅用戶 ID 判斷。
2. 將角色儲存喺資料庫
如果係單一團隊嘅 App,喺用戶表加一個 role 欄位就足夠。如果有團隊,就用成員表:
create table memberships (
user_id uuid references users(id),
organization_id uuid references organizations(id),
role text not null check (role in ('owner','admin','member','viewer')),
primary key (user_id, organization_id)
);
絕對唔可以讓用戶透過一般嘅個人檔案更新,自行設定角色。角色更改必須經過專用、並已做權限檢查嘅端點。
3. 喺伺服器統一檢查權限
寫一個共用嘅協助函式,例如 can(user, 'projects.delete', project),並喺每個讀取或更改資料嘅 API 路由、伺服器操作同背景工作中呼叫它。集中一個函式比分散喺程式碼各處嘅檢查更容易審查同測試。預設拒絕:如果冇任何規則允許某操作,就拒絕。
4. 限定每個查詢嘅範圍
所有查詢團隊資料嘅語句都應該包括團隊條件:where organization_id = :currentOrg,而唔係只係 where id = :id。咁樣可以防止有人將 /projects/123 改成 /projects/124 就能睇到另一間公司嘅專案。對於其他團隊嘅記錄,應該回傳「找不到」而唔係「禁止存取」,免得洩露該記錄存在。
5. 喺最重要嘅地方加入資料庫層保護
Postgres 行級安全性(RLS)可以讓資料庫本身執行邊啲資料列每位用戶可以睇到。當瀏覽器直接同資料庫溝通(例如某些託管後端)時,呢樣係必需嘅;就算係其他情況,對敏感資料表而言,它都是一個有用嘅第二層保護。
6. 喺介面反映角色
現在隱藏或停用用戶不能做嘅操作,令 App 唔會令人混淆。呢個只係為咗易用性;真正提供保護嘅係伺服器上嘅檢查。
7. 記錄敏感操作
記錄邊個更改咗角色、刪除咗資料或匯出咗記錄,以及發生嘅時間。審計記錄有助於處理支援問題同安全事故。
8. 以攻擊者角度測試
以每個角色登入,並嘗試權限表中每一項操作。然後再試吓唔應該成功嘅嘢:以檢視者身份呼叫管理員 API 路由、更改網址同請求中嘅 ID,或者移除自己作為最後一位擁有者。權限表定型之後,值得寫自動化測試。
有效嘅提示詞
加入角色式存取控制。每個機構有以下角色:擁有者、管理員、成員、檢視者,儲存於 memberships 表。權限如下:[貼上你嘅權限表]。建立一個伺服器端 can(user, action, resource) 協助函式,預設拒絕,並喺每個 API 路由使用。所有查詢都要以 organization_id 限定範圍。介面上隱藏用戶無權執行嘅操作,但安全保障絕對唔可以只依賴介面。
檢視呢個 App 中每一個 API 路由同伺服器函式。對每一項,列出佢讀取或更改咗乜嘢資料、有冇檢查用戶係咪已登入、有冇檢查角色,以及有冇將查詢限定於該用戶嘅機構。修正缺少檢查嘅地方,並展示清單俾我睇。
加入一個只限管理員使用嘅 /admin 頁面,讓擁有者可以更改成員角色。防止移除或降級最後一位擁有者,記錄每一次角色更改,包括由邊個更改以及幾時更改,並確保角色更改端點會拒絕任何非擁有者嘅人。
常見錯誤
- 只喺前端檢查角色。 API 仍然對任何呼叫它嘅人開放。
- 信任來自客戶端嘅 ID,例如請求內文中嘅
userId或role,而唔係使用 session。 - 未限定範圍嘅查詢,只按記錄 ID 讀取。
- 只喺頁面檢查角色,但 API 路由、匯出、檔案下載或 Webhook 未有檢查。
- 喺程式碼中硬寫以電郵識別管理員(
if email === 'me@...'),容易被忘記,亦難以更改。 - 太早加入太多角色,六個月後冇人說得清楚。
- 過期嘅 session:被降級嘅用戶要登出之後,先會失去管理員權限。對於敏感操作,應該由資料庫檢查角色,或者重新整理角色資料。
RBAC 檢查清單
- 已用白話寫成權限表,並決定好邊緣情況
- 伺服器從 session 得知用戶身份,而唔係從請求資料得知
- 角色儲存於資料庫;用戶唔可以自行更改
- 只有一個集中嘅權限檢查,預設拒絕,並用於每個路由
- 每個查詢都限定於用戶嘅機構或擁有權範圍內
- 瀏覽器可以直接接觸資料庫嘅地方,已設定行級安全性
- 介面隱藏用戶無權執行嘅操作(只係為咗易用性)
- 敏感操作都有記錄
- 每個角色都已測試,包括直接呼叫 API 同更改 ID
存取控制只係一個更大清單中嘅一項;AI 建立 App 嘅安全檢查清單涵蓋其餘項目。如果你要建立俾自己員工使用嘅工具,如何建立內部工具會展示角色應該放喺邊度。
Mythex 上嘅 RBAC
Mythex 唔會為你 App 嘅用戶提供內置嘅登入或角色系統。你要自行選擇驗證函式庫或供應商,並描述角色,然後 Agent 會將佢哋接入你嘅程式碼同專案嘅 Postgres 資料庫(為你的 App 加入登入)。Mythex 自己嘅工作區角色(例如擁有者同成員)控制邊位成員可以編輯你嘅 Mythex 專案,而唔係控制邊位用戶可以使用你已發布嘅 App。建立之前,先用計劃模式(Plan mode)確認權限表,然後使用上面嘅審查提示詞,並喺 Preview 中測試每個角色,之後才發布。文件中嘅安全提示詞係很有用嘅後續參考。
常見問題
咩係角色式存取控制?
角色式存取控制(RBAC)會根據每位用戶所持有嘅角色,決定佢可以做乜嘢,例如管理員、編輯或檢視者。權限係附加於角色,而唔係附加於個別人士,所以要改變某人可以做嘅事,只需要改變佢嘅角色。
驗證同授權有咩分別?
驗證(Authentication)係確認某人係邊個,通常透過登入完成。授權(Authorisation)則決定已登入嘅人可以睇到及做到乜嘢。RBAC 係進行授權嘅其中一種方法。
隱藏介面入面嘅按鈕,足夠限制存取嗎?
唔夠。任何人都可以直接呼叫你嘅 API,所以隱藏按鈕只會改變人哋睇到嘅嘢。每個讀取或更改資料嘅請求,都必須喺伺服器上,根據用戶嘅角色同該記錄是否屬於佢嘅帳戶作出檢查。
我應該用 Postgres 行級安全性(row-level security)嗎?
行級安全性可以讓資料庫本身執行邊啲資料列每位用戶可以讀取或寫入,係一個強大嘅安全網,特別係當前端直接同資料庫溝通嘅時候。但佢會增加複雜度,所以好多 App 會喺伺服器程式碼中執行權限,並對敏感資料表額外使用行級安全性作為另一層保障。