PHP复杂的基于角色的访问控制列表


PHP complex role-based access control lists

我已经制作了实现这个定制ACL系统所需的数据库和php代码。现在我必须"授权"当前用户,这就是我需要你建议的地方。

该系统基于对系统用户和系统模块的灵活权限分配。它还有一些预定义的,比如说用户组,还可以创建完全自定义的组。全局规则也可以应用于ACL之上,但它的优先级低于分配权限的组或用户。

为了更好地描绘它:

预定义组:

  1. 受限(禁止访问)
  2. 基本用户
  3. 超级用户
  4. 管理员
  5. 访问者(自定义组的示例)

以下是访问级别(名称/值对):

  • 禁止/0
  • 允许/1
  • 拒绝/2
  • 如果所有者/3允许

注意:"允许"在"不允许"上具有更高的优先级,因此,如果用户X在组A上是"不允许的",而在组B上是"允许的"的某个访问权限,那么他最终会是"允许"。另一方面,如果用户X作为"管理员"组的成员具有"完全访问权限",但如果他只是对某个访问权限"拒绝",则他最终没有访问权限,这意味着"拒绝"在"允许"上具有更高的优先级。

在顶层,你可能会有这样的东西:

  • "Administrator"*"1",表示管理员对系统具有完全访问权限
  • "访问者"*"0",表示访问者不允许进行任何活动

我的问题是如何处理这些检查?想象一下,我们有一个简单的授权机制。我们的$_SESSION['user']中会有一些索引,比如$_SESSION['user']['login'] = true;$_SESSION['user']['id'] = $row['user_id'],对吧?

现在,如果你想在你的脚本上实现这个机制,你会怎么做?

我可能会先查看全局访问规则。然后我会查看用户是否已经登录。如果是,只需获取他的所有组,然后查看权限表,查看哪些权限分配给了他的组和用户id,然后将它们存储在用户会话中。然后,当模块说这是我运行所需的权限时,我会查看用户是否有足够的权限访问请求的模块。

看起来很复杂!非常感谢您的帮助或建议!:)

编辑:

我没有使用任何框架。事实上我用过,但这是我自己的。所以,这里没有预先制作的ACL!

更新:

你知道如何有效地对ACL进行优先级排序(覆盖/替换?)吗?

Deny最高,其次是Allow,然后是Disallow。此外,分配给User的ACL最高,然后是Group的ACL,最后是Global的ACL。

以下是我最终得出的结论:

有一个Array,像这样:

$_SESSION['ACL'][$module][$action] = $access_level; // 0, 1, 2, 3

首先,我会查找所有全局规则*,并将它们放在数组中:

// The current user can see the map, applied by a global rule
$_SESSION['ACL']['map']['render'] = 1;
// All the other permissions are disallowed by default
$_SESSION['ACL']['*']['*'] = 0;
// He can edit his preferences, (Owner)
$_SESSION['ACL']['user']['*'] = 3;  

然后,我将查找基于组的ACL:

// User could access the Analyze module, all the methods 
// with Permission Name "report". Applied by being a member 
// of "Moderator" Group
$_SESSION['ACL']['analyze']['report'] = 1;
// User NOT allowed to access "groups" module, let say
// it reserved for "admin" group! - To see the ACLs' Overwriting!
$_SESSION['ACL']['groups']['*'] = 0;

毕竟,我会寻找用户分配的ACL:

// User have Full Access to the "groups" module.
// It's gonna replace the last ACL, applied by "Moderator" group
// Note that the order of processing ACLs is IMPORTANT!
$_SESSION['ACL']['groups']['*'] = 1;

我想它会很好用,有什么想法吗?

它现在运行得很好:)

以下是我在MVC环境中处理它的方法,创建一个具有以下结构的表:

(id, group_id(int), user_id(int), controller(varchar), action(varchar)) 

然后,我在group和user_id上使用-1来表示通配符,在控制器和操作上使用*。因此,在您的示例中,管理员可以执行任何操作(1,4,-1,)。或者说超级用户可以修改用户(2,3,-1,user,*)。或者,如果你想给一个人(user_id为34)一个权限,而不管他们在哪个组(3,-1,34,user,update)。如果您想将0-3存储为allow、disallow,只需添加一列即可。然后,您只需检查正在调用哪个控制器和操作,并查找适用于该人员的组(特别是他们)的任何权限。

只需创建您的权限/组表:

id, group/permission name

然后,创建您的多对多表链接组到用户:

id, user_id, group_id

如果您只是使用组权限,则不需要访问级别。

然后,在您的代码中,只需检查用户的组,如下所示:

function checkAccess($pageLevelRequired)
{
  // run query based on current user session id
  // run your query to check if the current user belongs to the group required to view this page.
}

有道理吗?