【问题标题】:Role based access with a twist?基于角色的访问有点扭曲?
【发布时间】:2011-02-01 11:59:02
【问题描述】:

我有一个基于角色的访问控制非常简单的 Web 应用程序。当前设置具有三个角色:

-超级管理员
-管理员
-用户

每个页面请求都会根据该页面的最低访问级别检查用户角色,并根据比较结果授予(或拒绝)对该页面的访问权限。

管理员和用户之间也存在一对多的关系;每个管理员负责一个或多个用户。

我现在面临的挑战是添加另一个角色 (LIMITED ADMIN) 并根据负责每个用户的管理员是否具有角色 ADMIN 或 LIMITED ADMIN 来限制他们的访问。

对于这种情况,是否有既定的最佳实践?修改我当前的访问逻辑来处理这种情况很简单,但是随着应用程序的增长,我开始怀疑是否应该转向更健壮的访问控制模型。访问控制列表是首先想到的,但它们似乎无法处理一个用户的访问权限可能受到另一个用户的角色限制的情况。

【问题讨论】:

    标签: php web-services security


    【解决方案1】:

    这里有两个问题。

    1. 您不是在“添加新角色”。你加了两个。 users-created-by-admins 和 users-created-by-limited-admins 必须具有不同的权限集这一事实意味着它们实际上是两个不同的角色。这样编码。基于继承将一个物理角色映射到两个逻辑角色的想法不必要地使事情复杂化。
    2. 您正在将安全模型更改为更细粒度。您的代码以前有三个角色,现在它有五个角色(不管第五个角色是否被官方认可)。

    访问控制列表在您的代码和给定角色之间提供了一定程度的间接性。无需检查用户的角色,您只需验证请求的操作 - 创建?读?更新?删除?是或否,简单的决定。代码永远不会改变。相反,分配角色的 UI 在创建 ACL 时会打包权限集。在用户创建屏幕中,管理员看到的权限由该管理员的级别定义 - 有限、普通或超级。但是一旦设置了 ACL,它是由管理员还是受限管理员设置的问题就无关紧要了。在运行时它只是简单地创建?读?更新?删除?是或否,简单的决定。

    完成此操作后,添加新角色就像在 ACL 上打包正确的权限集合一样简单。添加新权限很容易,您只需扩展 ACL。而且这些更改都不会影响以前的代码解释 ACL 的方式。

    请记住,特权是控制对真实资源的访问的有形事物。角色是由特权集合表示的抽象概念。一旦这两个东西在代码中分开,像你描述的那样的改变就会容易得多。两者相遇的唯一地方是在创建用户和分配权限的 UI 中。

    【讨论】:

    • 我认为这正是我需要做的。感谢您将其分解,现在更清晰了。
    【解决方案2】:

    您问错了问题,而不是问“用户是什么角色”,而应该问“当前用户可以做 x”。这会将意大利面条式代码变成非常灵活的基于角色的访问控制。

    错误代码:

      if ($user === 'Admin' || $user === 'Super Admin' || $user === 'SubAdmin'){
         // spaghetti
      }
    

    好代码:

    $resources = array(
       'edit_page',
       'view_page',
       'delete_page',
    );
    
    $roles = array(
        'admin' => array(
             'edit_page',
             'view_page',       
        ),
        'superadmin' => array(
             'edit_page',
             'view_page', 
             'delete_page',
        ),
        'user' => array(
             'view_page'
        ),
    );
    
    function can_do($x){
        $user_role;  // (currently logged in user role)
        return in_array($x, $roles[$user_role]);
    }
    

    有一个微妙但非常重要的区别。现在我们可以问,“当前用户可以做 x”

    if (can_do('view_page'))
    {
       // clean code
    }
    

    现在我们只需要询问我们是否可以做一些事情,添加一个新角色 (superduperadmin) 很简单,您只需要在一个地方进行更改。

    【讨论】:

    • 虽然我的代码没有“坏代码”示例那么糟糕,但我同意;访问控制列表比我目前所做的灵活得多。但是,我的新要求要求我根据关联管理员的角色确定“用户”访问权限。并非每个用户都将与相同的管理员相关联,并且有几个不同的“管理员”角色。
    【解决方案3】:

    要明确。不必每次访问资源时都检查用户的关联管理员,一种更简单且更易于维护的方法是将其实现为不同的用户角色。例如,当用户由 LIMITED ADMIN 创建时,他们的角色可能是 LIMITED USER。

    (当然,使用访问控制列表也可以达到相同的效果。同样的原则也适用——为用户分配明确的角色,而不是基于负责他们的管理员的隐式访问级别)。

    这样做的结果是,您还需要明确说明在更改管理员、禁用管理员帐户等时用户角色会发生什么。但我认为即使使用原始隐式方法,您 仍然必须考虑这些情况——事实上,你忽略的任何边界情况都更有可能导致安全漏洞,而显式角色本质上更安全。

    【讨论】:

    • 谢谢托德。这与 T.Rob 所说的类似。很有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 2010-09-11
    • 2017-10-19
    • 2011-04-25
    • 1970-01-01
    • 2020-06-22
    相关资源
    最近更新 更多