【问题标题】:Implementing ACL constraints, more than allow/deny实施 ACL 约束,不仅仅是允许/拒绝
【发布时间】:2011-09-02 03:51:01
【问题描述】:

我已经开发了一个小而有效的 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以解耦文件系统架构)然后将请求分派到处理程序,给定 group_id 关联该请求被列入该handler_key 的白名单。

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

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

我有一个flags 列,但是随着更多功能、组和约束要求的引入,这并不是面向未来的。我在想下面的方向,但是用什么?

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

不必要的澄清:

(注意:这里输入的是代码,而不是项目中的copypasta)

在这里澄清一些行话; handlers(特别是 web handlers)本质上是 controllers,对于那些熟悉 MVC 原型的人来说。

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

<?php
    $meta = array('subhandlers' => array());
    return function($request, $response) use($meta){
        $response['foo'] = 'bar';
    };

我的框架使用 web 处理程序API 处理程序; Web 处理程序将数据输入响应对象(基本上是分层视图的集合),该对象生成 HTML。数据是通过调用API处理程序获得的,API处理程序只是返回原始数据(API处理程序可以看作是模型的表示,回到典型的MVC)

复合处理程序本质上是一个抽象层,因为它们本身就是调用处理程序来聚合数据的处理程序。我当前的 ACL 检查实现对所有嵌套处理程序进行了粗略检查(通过 $meta,一个声明为处理程序元数据头的数组变量)例如:

<?php
    $meta = array('subhandlers' => array('my_subhandler'));
    return function($request, $response) use($meta){
        $someData = Caller::call('my_subhandler', array($request, $response));
        $response->bind($someData);
    };

【问题讨论】:

  • 您可能会觉得这很有趣:vimeo.com/2723800(ACL 已死)。
  • 感谢 Alix Axel;有趣的视频,我略读了一下,稍后我会完整观看;至于wiki条目,我以前读过它,它让我的大脑渗透,但我正在寻找解决方案。我会全力以赴学习如何钓鱼,但现在,我只需要吃一天。

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


【解决方案1】:

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

关于你的问题,我从来没有实现过这个,我只是模糊地知道如何(或不能)构建这样的系统,所以用一个(或几个)颗粒接受我的输入盐

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

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

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

如果您有专有符号,则可以通过 tokenizing 规则轻松解析和验证这一点,也可以使用 DatePeriodDateInterval 甚至像 crontab 那样的模数运算符。

你的第二个例子:

只允许给定的组调用 修改“拥有”数据的处理程序; IE: 相关用户创建的数据。

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

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

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

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

我认为这种规则必须特定于应用程序逻辑,真正的通用解决方案很难实现,Zed Shaw 在他的演讲中提到他提出了一个仅使用 400 行代码的完整解决方案,我很想知道他是怎么做到的。

标志(以位存储)是指定一个或多个约束组合的一种很好的(虽然神秘)方式,但根据我的经验,最好先定义所有约束。

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

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

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

如果我的回答对你没有多大帮助,我很抱歉,但我觉得这个问题很有趣,我希望其他人能提出一个更好的问题,AFAIK 没有魔杖可以做到这一点。

【讨论】:

  • 感谢 Alix Axel;你的建议确实让我思考。回顾了我的架构选择后,我认为我找到了一个非常合适的解决方案,它使实现保持开放式并且完全与应用程序无关。检查我自己的答案以获取更新,请随时批评。
【解决方案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-able 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_keys 遗漏的情况作为基本的白名单检查处理; 允许如果/拒绝如果不是

所以我的应用程序目录开始看起来像这样:

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

【讨论】:

  • 嗨 - 我很想看看你是否在这方面取得了进展,所以你不再有像 $dayBegin + 32400 这样的硬编码术语?正如@Alix 建议的那样,创建一种机制来解析数据库中特定于角色的约束似乎是一个不错的方法。我一直在做类似的事情,但还没有确定。
猜你喜欢
  • 2016-02-09
  • 2013-09-22
  • 1970-01-01
  • 1970-01-01
  • 2012-04-14
  • 1970-01-01
  • 2021-06-30
  • 2011-09-13
  • 2016-02-22
相关资源
最近更新 更多