我开发了一个小而有效的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 |
+----------+---------------+ +---------------+---------------+
( user
和group
为简洁而排除,但他们的模型并不罕见)
无论如何,我的框架通过处理程序/路径表(来解耦文件系统架构)将URI路由到适当的handler_key
。然后,在{{{}>的情况下将请求分派给处理程序。与请求关联的1}}已列入group_id
的白名单。
我很好奇,实现存储/检查任意(用户定义的)约束的最佳方法是什么?案例示例如下:
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
答案 0 :(得分:4)
我在评论中发布的视频与您分享的视频有一些类似的想法,但没有代码。
关于你的问题,我从来没有实现过这个问题,而且我对于如何构建这样的系统只能有一个模糊的想法,所以用一个(或几个)粒子输入我的输入盐。
您必须做的第一件事是确定用户可以限制的约束,忘记任意数据,定义用户可以和不能定义的内容是最重要的一点。
下一步是定义一些您可以轻松解析和验证的符号或数据结构,例如,基于时间的限制,您有以下可能性:
如果您有一个propper表示法,您可以通过tokenizing规则轻松解析并验证这一点,并且可能使用DatePeriod或DateInterval或甚至像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/
: