昨天談到 RBAC 用 Role 當作 User 與 Permission 之間的中間層,能有效降低管理成本,但也提到一個限制:如果規則牽涉大量動態條件(例如「只能在上班時間存取」「只能存取自己部門的資源」),RBAC 就容易出現 Role Explosion——角色數量隨著條件組合不斷增加,最後比逐一設定 Permission 更難維護。
今天要介紹的 ABAC(Attribute-Based Access Control,屬性型存取控制),就是為了解決這類問題而設計的模型。ABAC 不再只看「你是什麼角色」,而是同時檢查 Subject、Resource 與 Environment 的各種屬性,再依照政策動態計算出 Allow 或 Deny。
今天內容涵蓋:
ABAC(Attribute-Based Access Control,屬性型存取控制)不只看 User 擁有什麼 Role,而是根據請求當下的屬性,動態決定 Allow 或 Deny。一次 ABAC 判斷可以理解為:某個 Subject 想對 Resource 執行 Action,系統再依照 Environment 與 Policy 檢查相關屬性。
| 判斷資訊 | 說明 | 常見屬性範例 |
|---|---|---|
| Subject | 提出請求的人或服務 | 部門、職等、Role、Clearance Level |
| Resource | 要存取的物件 | 擁有者、機密等級、資料分類 |
| Action | 要執行的操作 | Read、Write、Delete |
| Environment | 請求發生時的情境 | 時間、地點、裝置類型 |
將表格中的資訊組合起來,就能形成一條完整的 ABAC Policy。例如:Gloria 所屬的部門是 HR、要讀取的資料標記為 internal,而且請求發生在下午六點以前時,允許 Gloria 執行 Read。
系統收到請求後,會依序確認 Gloria 的部門、資料的機密等級、這次執行的 Action,以及請求發生的時間。所有條件都成立時,結果才是 Allow;只要其中一項不符合,這條 Policy 就不會允許存取。若沒有其他 Policy 明確允許,系統便採用預設 Deny。
同一個請求可能同時符合多條 Policy,因此實作時還要先定義衝突處理方式,例如 Deny 優先。這樣才能避免一條 Policy 允許、另一條 Policy 拒絕時,系統產生不一致的判斷。
💡XACML(eXtensible Access Control Markup Language)是描述 ABAC Policy 的標準之一;不同平台通常會使用各自的 Policy 語法表達這類規則。
| 比較項目 | RBAC | ABAC |
|---|---|---|
| 存取控制依據 | Role | 屬性(User/Resource/Environment) |
| 精細度 | 較粗(以角色為單位) | 較細(以屬性組合為單位) |
| 彈性 | 有限 | 高,可即時反映情境變化 |
| 複雜度 | 較簡單 | 較複雜,政策數量可能快速增加 |
| 管理方式 | 管理 Role 與指派 | 管理 Policy 與屬性來源 |
| 適合情境 | 權限結構穩定、職務清楚 | 需要動態、依情境調整的存取控制 |
兩者不是互斥的選擇。實務上常先用 RBAC 建立基本權限,再用 ABAC 補上少數需要動態判斷的條件。這樣既能保留 Role 容易管理的優點,也能處理時間、部門或資源標籤等情境。
OAuth 2.0 與 ABAC 處理的是不同階段:OAuth 2.0 讓 Client 取得 Access Token,ABAC 則由 Resource Server 根據屬性與 Policy,判斷這次請求是否可以執行。兩者可以搭配使用,但不能把「持有 Token」直接視為「一定有權限」。
如果 Access Token 採用 JWT 格式,Token 中的 Claim 通常只提供 Subject 相關資訊。Resource Server 還要從其他來源補上 Resource、Action 與 Environment,組成一次完整的授權判斷資料。例如:
{
"subject": {
"id": "usr_gloria",
"department": "HR",
"clearance": "internal",
"tenant_id": "shop-a",
"scope": ["document:read"]
},
"resource": {
"id": "doc_payroll_2026",
"type": "document",
"classification": "confidential",
"tenant_id": "shop-a"
},
"action": "read",
"environment": {
"time": "2026-09-06T14:00:00+08:00",
"network": "corporate"
}
}
這不是 Access Token 原本的完整內容,而是 Resource Server 將不同來源的屬性整理成同一份授權判斷資料。JSON 與來源的對應關係如下:
| JSON 欄位 | 資料來源 | 本例內容 |
|---|---|---|
subject |
Access Token 的 Claim | User ID、部門、權限等級、Tenant、Scope |
resource |
文件資料或 Resource Metadata | 文件 ID、類型、機密等級、Tenant |
action |
API Request | read |
environment |
Request Context | 請求時間、網路環境 |
接著,Resource Server 會把這些資料帶入授權判斷流程:
因此,即使 Token 顯示 Gloria 屬於 HR,並具有 document:read Scope;只要目標文件的機密等級高於 Gloria 的 Clearance Level,ABAC Policy 仍然可以拒絕請求。
💡Token 只提供屬性,最後仍由 ABAC Policy 決定 Allow 或 Deny。Token 中的 Claim 是簽發當下的資料;例如 Gloria 轉到其他部門後,舊 Token 可能仍寫著
department=HR。敏感權限因此通常會使用較短的 Token 有效期限,或在每次請求時查詢最新資料。
ABAC 彈性高,但會增加政策設計與執行成本。實際導入前,可以先評估以下幾點:
⚠️ABAC 不是用來取代 RBAC 的萬用解方。多數團隊會保留 RBAC 處理穩定的職務權限,只在少數需要「依情境動態判斷」的場景,例如多租戶隔離、跨部門資料存取、依時間或裝置限制時,才加入 ABAC 規則。
本篇可以整理成以下幾個重點:
下一篇將介紹 ACL(Access Control List)與 ReBAC(Relationship-Based Access Control),比較「直接替資源列出存取名單」與「根據彼此關係授權」這兩種做法。