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

Dan*_*ugg 8 php permissions model-view-controller acl constraints

我已经开发了一个小而有效的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        |
+----------+---------------+    +---------------+---------------+
Run Code Online (Sandbox Code Playgroud)

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

无论如何,我的框架handler_key通过处理程序/路径表 URI路由到适当的(以解耦文件系统体系结构)然后将请求分派给处理程序,因为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        |     ?      |
+---------------+---------------+------------+
Run Code Online (Sandbox Code Playgroud)

不必要的澄清:

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

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

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

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

我的框架使用Web处理程序API处理程序 ; Web处理程序将数据提供给生成HTML 的响应对象(基本上是分层视图的集合).通过调用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);
    };
Run Code Online (Sandbox Code Playgroud)

Dan*_*ugg 2

在审查了我的架构选择之后,我明显意识到我可以利用我的handler样式请求处理方法。

请批评和/或嘲笑和/或为这个提议点赞

出于这些目的,检查用户是否具有权限的请求可以被视为简单的另一个请求,因此需要它自己的 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             |           :
+---------------+-------------+------------------------+ - - - - - +
Run Code Online (Sandbox Code Playgroud)

通过添加NULL-ableconstraint_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',
);
Run Code Online (Sandbox Code Playgroud)

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());
};
Run Code Online (Sandbox Code Playgroud)

遗漏constraint_handler_keys的情况按基本白名单检查处理;允许如果/拒绝如果不

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

:
+- application/
|   +- config/
|   +- views/
|   +- handlers/
|       +- acl/
|       +- api/
|       +- web/
:
Run Code Online (Sandbox Code Playgroud)