实现ACL约束,超过允许/拒绝

时间:2011-05-25 22:09:22

标签: php model-view-controller permissions constraints acl

我开发了一个小而有效的MVC样式框架,用于应用程序,我正在实施ACL每请求检查。

快速详情:PHP 5.3+; MySQL 5.1+;自定义框架,“类似MVC”

截至目前,ACL检查很简单“ deny-if-not white-listing ”;可以为每个group分配对某些请求处理程序的权限。例如:

privilege                       permission
+----------+---------------+    +---------------+---------------+
| group_id | permission_id |    | permission_id | handler_key   |
+----------+---------------+    +---------------+---------------+
|     1    |       1       |    |       1       | lorem_ipsum   |
|     1    |       2       |    |       2       | hello_world   |
|     2    |       3       |    |       3       | foobar        |
+----------+---------------+    +---------------+---------------+

usergroup为简洁而排除,但他们的模型并不罕见

无论如何,我的框架通过处理程序/路径表(来解耦文件系统架构)将URI路由到适当的handler_key。然后,在{{{}>的情况下将请求分派给处理程序。与请求关联的1}}已列入group_id的白名单。

我很好奇,实现存储/检查任意(用户定义的)约束的最佳方法是什么?案例示例如下:

  • 仅允许给定的组在工作日的8:00到17:00之间调用处理程序。
  • 仅允许给定组调用处理程序来修改“拥有”数据;即:由关联的handler_key创建的数据。 此检查可能涉及检查与处理程序要修改的内容相关联的user字段以及与请求关联的user_id

我有一个user_id列,但是随着更多功能,组和约束要求的引入,这不是面向未来的。我正在考虑以下方向,但要使用什么?

flags

不必要的澄清:

注意:代码是在这里输入的,不是来自项目的copypasta

澄清一些行话;对于熟悉MVC原型的人来说,处理程序(特别是Web处理程序)本质上是控制器

它们的具体实现是一个PHP文件,它返回一个由调度程序或子处理程序调用程序调用的函数。例如:

permission
+---------------+----------------------------+
| permission_id | handler_key   | constraint |
+---------------+---------------+------------+
|       1       | lorem_ipsum   |     ?      |
|       2       | hello_world   |     ?      |
|       3       | foobar        |     ?      |
+---------------+---------------+------------+

我的框架使用网络处理程序 API处理程序; Web处理程序将数据提供给生成HTML的响应对象(基本上是分层视图的集合)。通过调用API处理程序获取数据,这些处理程序只返回原始数据(API处理程序可以被视为模型的表示,返回到典型的MVC)

复合处理程序本质上是一个抽象层,因为它们是处理程序本身,它们调用处理程序来聚合数据。我目前对ACL检查的实现,粗略检查所有嵌套处理程序(通过<?php $meta = array('subhandlers' => array()); return function($request, $response) use($meta){ $response['foo'] = 'bar'; }; ,声明一个数组变量作为处理程序的元数据头)例如:

$meta

2 个答案:

答案 0 :(得分:4)

我在评论中发布的视频与您分享的视频有一些类似的想法,但没有代码。

关于你的问题,我从来没有实现过这个问题,而且我对于如何构建这样的系统只能有一个模糊的想法,所以用一个(或几个)粒子输入我的输入盐

您必须做的第一件事是确定用户可以限制的约束,忘记任意数据,定义用户可以和不能定义的内容是最重要的一点。

下一步是定义一些您可以轻松解析和验证的符号或数据结构,例如,基于时间的限制,您有以下可能性:

  • 具体日期时间(2011-05-26)
  • 日期时间范围(2011-05-26至2011-05-31)
  • 递归日期时间(201x-05-26或每周五)
  • 逻辑(和/或/ xor)运算符

如果您有一个propper表示法,您可以通过tokenizing规则轻松解析并验证这一点,并且可能使用DatePeriodDateInterval或甚至像crontab这样的模数运算符。

你的第二个例子:

  

仅允许给定组调用   修改“拥有”数据的处理程序;即:   由关联用户创建的数据。

对我来说听起来像普通的ACL:

  • 资源:特定数据
  • 角色:特定用户

当然,你有更复杂的规则,如:

  

批准记录的用户必须   具有相同或更高的水平(在   与用户相同的安全名称空间)   谁创造了记录,但他们不能   是同一个用户。

我认为这种规则必须特定于应用程序逻辑,并且真正的通用解决方案将非常难以实现,Zed Shaw在他的演讲中提到他提出了一个仅使用400行代码的完整解决方案,我会非常有兴趣了解他是如何做到的。

标志(存储在位中)是指定一个或多个约束的组合的一种很好的(尽管是神秘的)方式,但根据我的经验,如果你定义所有的apriori约束会更好。

由于您似乎并不确切知道要检查的约束,我建议您为要检查的几种类型的限制创建符号:

  • 基于时间
  • 基于用户/资源
  • ...

然后实现解析的方法(可能带有暗示版本的符号,以便将来可以迁移)并验证所有约束。

我很抱歉,如果我的答案对你没什么帮助,但我觉得这个问题很有意思,我希望别人能找到一个更好的答案,AFAIK没有魔杖可以做到这一点。

答案 1 :(得分:2)

在审核了我的架构选择之后,我发现我可以利用我的handler样式请求处理方法。

请,批评和/或嘲笑和/或高五这个命题作为保证

为了这些目的,检查用户是否具有权限的请求可以将视为另一个请求,因此需要它自己的处理程序。例如:

permission
+---------------+--------------------------------------+- - - - - -+
| permission_id | handler_key | constraint_handler_key | arguments :
+---------------+-------------+------------------------+ - - - - - +
|       1       | lorem_ipsum | user_check_owner       |           :
|       2       | hello_world | user_check_owner       |           :
|       3       | foobar      | time_check             |           :
+---------------+-------------+------------------------+ - - - - - +

添加NULL - 能constraint_handler_key列后,可以通过编程方式创建新约束,并进行管理委派。

当请求触发时,框架会聚合处理程序链,并将其与白名单进行比较,就像它已经做的那样。在所述事件的constraint_handler_key的情况下(可能与参数作为上表中表明)它执行在查找的handlerTable与该请求类型相关联:

// web handlers handlerTable example
return array(
    'lorem_ipsum' => PATH_WEB_HANDLERS . 'path/to/lorem_ipsum.handler.php',
);

// acl handlers handlerTable, follows same format
return array(
    'time_check' => PATH_ACL_HANDLERS . 'time/check.handler.php',
);

API处理程序也相同

ACL处理程序只返回布尔值,从而继续或结束权限检查序列,因此也就是整个请求。

// time_check acl handler, allow if current time between 9am - 5pm
return function($request){
    $dayBegin = time() - (time() % 86400);
    return (time() > ($dayBegin + 32400) && ($dayBegin + 61200) > time());
};

遗漏constraint_handler_key s的案件作为基本白名单检查处理; 允许-如果/拒绝-IF-不

所以我的应用程序目录将如下所示:

:
+- application/
|   +- config/
|   +- views/
|   +- handlers/
|       +- acl/
|       +- api/
|       +- web/
: