Table of contents


Apache Shiro (之前叫JSecurity)是RBAC權限系統,也就是以角色為主的權限。 目前survey過的幾套java base的權限系統有

  1. Spring Security(之前叫Acige Security)
  2. JPA Security
  3. Apache Shiro(之前叫JSecurity或ki)
Spring Security

之前做文件管理系統時有採用過,很強大,但使用上也很複雜,特點是透過AOP來管控access, 而且可以依權限產生相對的Query (sql query or JPA query). 但目前一定要搭著Spring使用:-(

JPA Security

透過Annotation控管權限,特點是owner-ship(擁有權)的處理,而且會依不同的權限,產生不同的query條件(where conditions)

Apache Shiro

Apache Shiro的特色在permission的管控,所有的permission是透過特定格式的文字來記錄,語法大概像這樣 domain:operations:instance,並搭配wildcard(通配字元)進行較大範圍的控制。

WildcardPermission

Format:

domain:action:instances

Simple Usage

editNewsletter 新聞編輯的權限
*              所有的權限(root)

Multiple Levels

newsletter:edit             新聞編輯的權限
newsletter:edit,remove,add  新聞編輯、移除、加入的權限
newsletter:*                新聞所有的權限
*:view                      所有VIEW的權限

Instance-level Access Control

newsletter:edit:12,13,18   對12,13,18這三則新聞編輯的權限
newsletter:*:12,13,18      對12,13,18這三則新聞所有的權限
newsletter:*:*             對所有新聞的所有權限

Modeling

以下是Shiro的創建者Les Hazlewood建議的modeling方式

Les general rule of thumb:

  1. a Role is a named Set of permissions
  2. a User ‘has’ a Set of one or more Roles
  3. a User ‘has’ a Set of permissions for that-user-only permissions (not shared with anyone else - otherwise they’d go in a Role)
  4. a Group is a named Set of ‘Party’ objects (a User is a Party and a Group is a Party - allowing for instances of both to exist in hierarchical Party trees)

Les並建議不要採用deney的方式modeling權限,而且採用Aggregated Roles的方式 (原文參考)

針對第三點,Kent還是偏好用that-user-only role,而不是直接把permission指派給user

Instance Level範例

權限系統中,Kent個人認為,最關鍵也是最麻煩的地方在對Instance Level resource的管控。 也就怎如何控制,具有相同角色(也就是擁有相同的權限)的人對相同類型的資源,有不同的控制能力。 舉例來說: IT Manager跟ServiceDesk Manager都具有部門主管的角色,所以都擁有業務審核(auditing)的權限, 但因為IT Manager是IT部門主管,Service Desk Manager是ServiceDesk主管,所以

  • IT Manager只能審核IT部門的業務
  • Service Desk Manager只能審核ServiceDesk部門的業務

正常來說設計成

  • 部門主管擁有審核的權限

會比

  • IT Manager只能審核IT部門的業務
  • Service Desk Manager只能審核Service Desk部門的業務

來的直覺,而且比較符合Business Rules,而且不會造成角色爆炸問題(如果有100個部門,就要需100個角色^1)^)

要達到第一種的設計方式,就是要從Instance Level的權限來做管控。 像這樣:

# IT Manager
performance:auditing:it_department_id
# Service Desk Manager
performance:auditing:it_servicedesk_id

performance:auditing:it_department_idperformance:auditing:it_servicedesk_id指派給Manager Role時 Manager Role會同時具有IT, ServiceDesk Manager的權限,可是,我們要的是讓每個部門的Manager有專屬的權限,此時就需要把權限指派給 User,更好的方式是讓每個User擁有自已專屬的Role,然後指performance:auditing:it_department_idperformance:auditing:it_servicedesk_id指派給User的role,並讓user具有manager的role 。這樣,不但可以保持只有一個叫Manager的Role,而且IT manager跟Service Desk的權限是不同的。 ^2)^

Things that need to know

  1. Shiro的實際運用上,permission會比role更實用,實作時, 應該是針對permission。
  2. Shiro會cache住AuthorizationInfo,你可以透過clearCachedAuthorizationInfo來refresh caching
  3. Shiro並未提供直接的API去異動role, permission…,必須自行extend Realm以達到這個功能
  4. Shiro並未提供直接Group,Role Hierarchal, Role(Group) Inheritance等data model,但有需要的話,可以自行實作 (範例)

Resources

^1)^ 也有人主張可以把權限直接直派給而不是角色,來解決這樣的問題,詳見note說明

^2)^ 或許有更好的解法