基于角色的访问有一个扭曲?

时间:2011-01-31 22:47:32

标签: php web-services security

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

-SUPER ADMIN
-admin
- 用户

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

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

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

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

3 个答案:

答案 0 :(得分:1)

你问的是错误的问题,而不是问'用户应该扮演什么样的角色''当前用户可以做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)很容易,你只需要在一个地方进行更改。

答案 1 :(得分:1)

明确。除了每次访问资源时都必须检查用户的关联管理员,更简单,更易于维护的方法是将其作为独特的用户角色来实现。例如,当用户由LIMITED ADMIN创建时,他们的角色可能是有限用户。

(当然,访问控制列表也可以实现相同的效果。同样的原则适用 - 为用户分配一个显式角色,而不是基于负责它们的管理员的隐式访问级别。)

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

答案 2 :(得分:1)

这里有两个问题。

  1. 您不是“添加新角色”。你要加两个。用户创建的管理员和用户创建的有限管理员必须具有不同的权限集,这意味着这些实际上是两个不同的角色。以这种方式编码。基于继承将一个物理角色映射到两个逻辑角色的想法不必要地使事情复杂化。
  2. 您正在将安全模型更改为更细粒度。你的代码以前有三个角色,现在它有五个(无论第五个是否被官方认可)。
  3. 访问控制列表提供代码与给定角色之间的间接级别。您只需验证所请求的操作 - 创建?而不是检查用户的角色。读?更新?删除?是或否,简单的决定。代码永远不会改变。相反,在创建ACL时,分配角色的UI会打包特权集。在用户创建屏幕中,管理员看到的权限由该管理员的级别定义 - 限制,常规或超级。但是一旦ACL被设置,它是由管理员还是有限管理员设置的问题就无关紧要了。在运行时它只是创建?读?更新?删除?是或否,简单的决定。

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

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