2013-07-01 59 views
10

我正在嘗試使用Apache Shiro框架來保護我的Web應用程序(UI基於Vaadin 6)。通過Shiro網站上的所有示例,並搜索了幾個小時,但我無法找到一個乾淨的方式來處理以下要求。如何使用Apache Shiro處理分層角色/權限?

假設應用程序是一種項目管理工具,用戶正在創建活動,屬於公司層次結構中的特定部門。每個用戶可以在多個部門工作,並且在每個部門中具有不同的安全角色。例如:

 
Department A  - User is 'Manager' here 
Department B 
    Department C  - User is 'Admin' here 
    Department D 

用戶是在部門A 「用戶管理器」是在部ç 用戶「管理」也應該繼承「管理」爲部d(這是系的C祖先)的作用。

所以,基本的權限檢查(假設我要查看屬於一些部門的活動)將是:

  1. 檢查活動用戶試圖查看所屬部門用戶有一定作用;
  2. 檢查用戶是否需要基於他的角色在此部門的許可。

我目前停留在理解如何實施不僅僅是「系統廣角」,而是「在這個特定部門的作用」的概念。

如何將上面的示例轉換爲像「activity:view:123」這樣的權限字符串?我將如何檢查業務邏輯中的權限?

另一個疑問是Shiro的實現,我想使用一些開箱即用的解決方案將最小的努力提供我自己的實現。但是,Shiro的內置實現似乎只適用於簡單情況。是否有任何複雜的授權實施示例(可以涵蓋上述情況)?

回答

3

只是想描述一下我對這個問題的解決方法,這對某些人可能是有用的。我覺得這可能不是最佳的,所以仍然歡迎任何有關更清潔實施的建議。

假設我需要確保採取以下行動:

  • 活動:編輯
  • 活動:鑑於

而且我也需要確保權限是不是全系統,而是依賴關於我在特定部門的角色。我所做的是在我的Realm中爲用戶明確添加了「依賴於部門」的權限。例(見層次結構在後):

  • DEP_A:活動:鑑於
  • DEP_C:活動:鑑於
  • DEP_C:活動:編輯

每次我要檢查行動針對某些活動是否允許,我創建了一個要檢查的權限列表。例如:

活動A屬於D部門,我想「查看」它。權限檢查將是:

  • DEP_D:活動:鑑於
  • DEP_C:活動:鑑於
  • DEP_B:活動:鑑於

如果我是小編在部門C,我會有'DEP_C:活動:查看'權限,因此 檢查將通過。這就允許在公司結構層次結構中實現權利繼承。

這裏是我的服務類的代碼snipplet負責權限檢查:

@Override 
    public void checkIfOperationPermitted(SecurityOperation operation, 
     Object object) 
    { 
     final Subject currentUser = SecurityUtils.getSubject(); 

     if(currentUser.isPermitted(
     SecurityOperation.SYSTEM_ADMIN.getPermissionString()) || 
     currentUser.hasRole("admin")) 
     { 
     // no need to check anything else, 
     // admin is system wide role. 
     return; 
     } 

     if(object instanceof Activity) 
     { 
     // Activity permissions fully depends on organization and 
     // product hierarchies. PermissionResolver is just a class 
     // which generates list of permission strings based on 
     // department activity is belonging to. 
     Activity a = (Activity) object; 
     List<String> permissionsToCheck = 
      permissionResolver.resolveHierarchicalPermissions(operation, a); 
     boolean permitted = false; 
     for(String permission: permissionsToCheck) 
     { 
      if(currentUser.isPermitted(permission)) 
      { 
       permitted = true; 
       break; 
      } 
     } 
     if(!permitted) 
     { 
      throw new UnauthorizedException("Access denied"); 
     } 
     } 
     else 
     { 
     // Check for system wide permissions 
     currentUser.checkPermission(operation.getPermissionString()); 
     } 
    } 

我在想另一種方法是增加所有這些權限的用戶在我的領域,但他拒絕透露該公司自層次結構可以在一般包含N層 - 這大大增加了特定用戶權限列表中的重複(內存使用)。