如何使用 Apache Shiro 处理分层角色/权限?

Posted

技术标签:

【中文标题】如何使用 Apache Shiro 处理分层角色/权限?【英文标题】:How to deal with hierarchical roles/permissions using Apache Shiro? 【发布时间】:2013-06-28 15:40:08 【问题描述】:

我正在尝试使用 Apache Shiro 框架来保护我的 Web 应用程序(UI 基于 Vaadin 6)。浏览了 Shiro 网站上的所有示例,也搜索了几个小时,但我找不到处理以下要求的干净方法。

假设应用程序是一种项目管理工具,用户在其中创建活动,属于公司层次结构中的特定部门。每个用户可能在多个部门工作,并且在每个部门中具有不同的安全角色。示例:

部门 A - 用户在这里是“经理” B部 部门 C - 用户在这里是“管理员” D部

用户是部门 A 的“经理” 用户是 C 部门的“管理员” 用户还应该继承 D 部门(C 部门的祖先)的“管理员”角色。

因此,基本权限检查(假设我想查看属于某个部门的活动)将是:

    检查用户尝试查看的活动是否属于部门用户具有角色; 根据用户在该部门中的角色检查用户是否需要权限。

我目前对如何实施不仅是“系统范围的角色”,而且是“在这个特定部门中的角色”概念的理解很困难。

如何将上述示例转换为“activity:view:123”之类的权限字符串?以及如何检查我的业务逻辑中的权限?

还有一个疑问是 Shiro 的实现,我想使用一些开箱即用的解决方案,以尽量减少提供我自己的实现的努力。然而,Shiro 的内置实现似乎只为简单的情况而设计。是否有任何复杂授权实施的示例(可以涵盖上述情况)?

【问题讨论】:

【参考方案1】:

只想描述我对这个问题的解决方案,这可能对某人有用。我觉得这可能不是最佳的,所以仍然欢迎任何关于更清洁实施的建议。

假设我需要保护以下操作:

活动:编辑 活动:查看

而且我还需要确保权限不是系统范围的,而是取决于我在特定部门的角色。我所做的是为我的领域中的用户明确添加“部门相关”权限。示例(参见帖子中的层次结构):

DEP_A:activity:view DEP_C:activity:view DEP_C:activity:edit

每次我想检查是否允许对某些活动执行操作时,我都会创建一个要检查的权限列表。示例:

活动 A 属于 D 部门,我想“查看”它。检查权限为:

DEP_D:activity:view DEP_C:activity:view DEP_B:activity:view

如果我是 C 部门的管理员,我将拥有“DEP_C:activity:view”权限,因此 检查将通过。这允许在公司结构层次结构中实现权限继承。

这是我的服务类中负责权限检查的代码片段:

   @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 层 - 这大大增加了特定用户权限列表中的重复(内存使用),因此拒绝了。

【讨论】:

以上是关于如何使用 Apache Shiro 处理分层角色/权限?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用带有 LDAP 身份验证的 Apache Shiro 添加角色授权

如何根据 HTTP 请求方法使用 Apache Shiro 进行基于角色的授权

Apache shiro:使用 ldap 进行用户身份验证,使用数据库获得角色/权限?

Apache Shiro 使用手册Realm 实现

Apache Shiro 决定登录后使用啥角色

Apache Shiro - 使用数据库读取用户、角色和权限