Php 细粒度访问控制
我熟悉我们正在开发的基于web的管理应用程序的一整套验证用户身份的方法,甚至还有各种跟踪授权的技术 但是,我的问题是,您建议我如何实现提供以下功能的细粒度访问控制机制:Php 细粒度访问控制,php,mysql,authorization,access-control,Php,Mysql,Authorization,Access Control,我熟悉我们正在开发的基于web的管理应用程序的一整套验证用户身份的方法,甚至还有各种跟踪授权的技术 但是,我的问题是,您建议我如何实现提供以下功能的细粒度访问控制机制: 用户属于“角色”或“组”,如“销售人员”、“计划”等 管理员菜单系统仅显示具有与用户角色相关功能的“页面” 这些页面中的特定功能有限制-例如,在“新预订”页面上,“销售人员”用户可以“仅在将来”发布预订,“编辑预订”页面上可以“从现在起一周”编辑预订。然而,“规划”用户可能被允许追溯到“一周前”并编辑自己“任何时间段”的预订,但
Zed Shaw在CUSEC的一次演讲中谈到了为什么“ACL已经死了”——警告,前面还有很多Zend框架 您可以轻松处理1。二,。和 对于第3个问题,您必须在模型中查询ACL对象,并手工完成许多工作。您也可以将Zend框架用于表单,并根据用户角色权限包括特定的表单元素验证器 编辑:
如果您不想走ZF路线,您至少可以看看在ZF中如何处理ACL。为了实现一种“本地”方法,而不是依靠一个框架,我一直在玩弄以下内容。有人会评价这种方法吗?你预见到什么陷阱了吗
// Check database for existence of this $user against this $object.
function get_permission($user, $object){
// Query goes here...
if( ... ){
return $permission;
} else {
return FALSE;
}
}
上述函数将查询数据库并输出如下内容:
// Result of role-object query.
role_ID object_ID permission
------- --------- ----------
salesperson new_booking_date 'min' => 'now', 'max' => '+1 year'
planning new_booking_date 'min' => '-1 week', 'max' => '+1 year'
salesperson edit_booking_date 'this_user_min' => 'now', 'this_user_max' => '+1 week', 'other_user_min' => 'now', 'other_user_max' => '+1 week'
planning edit_booking_date 'this_user_min' => '-1 week', 'this_user_max' => '+1 year', 'other_user_min' => '-1 week', 'other_user_max' => '+1 week'
包含表单输入的页面中的以下代码:
// Draw form control with javascript date validation...
$this_permission = get_permission($this_user, 'new_booking_date');
if($this_permission){
$html->datepicker('min' => $this_permission['min'], 'max' => $this_permission['max']);
}
预订完成后,另一个页面允许我们编辑该字段:
// Verify POST data...
$this_permission = get_permission($this_user, 'edit_booking_date');
if($this_permission){
if($this_user == $author_user && $_POST['date'] >= strtotime($this_permission['this_user_min'], $date_ref) && $_POST['date'] <= strtotime($this_permission['this_user_max'], $date_ref)){
// Update database...
} elseif($_POST['date'] >= strtotime($this_permission['other_user_min'], $date_ref) && $_POST['date'] <= strtotime($this_permission['other_user_max'], $date_ref)){
// Update database...
}
}
//验证POST数据。。。
$this_permission=get_permission($this_user,'edit_booking_date');
如果($this_permission){
如果($this_user==$author_user&&$$u POST['date']>=strotime($this_permission['this_user_min'],$date_ref)&$$u POST['date']=strotime($this_permission['other_user_min'],$date_ref)&$$POST['date']如果您想构建真正的细粒度访问控制(FGAC),请查看我关于MySQL的文章:
基本上,您不希望业务代码依赖于FGAC实现,也不希望在业务规则的select
语句的where
子句中混合使用FGAC代码。
这篇文章展示了避免SQL语句混乱的解决方案。我开发了一个名为的库,我认为它可以很好地满足您的需要。它目前支持完全托管访问,允许您在每个页面上使用一个调用(当然,我建议使用include)如果用户无法访问页面,则自动重定向用户,以及从数据库自动检索角色(如果您使用附带的MySQL表设置脚本在数据库中实现角色),语法非常简单
创建弹跳器:
$bouncer = new Bouncer();
添加您的角色(手动):
或从数据库:
// conf_* values are set in a config file, or you can pass them in explicitly
$bouncer->readRolesFromDatabase(conf_hostname, conf_username, conf_password, conf_schema, "mysql");
添加一个用户并给他们一些角色(注意:有一个名为BouncerUser的类,您的用户类可以扩展它,它提供您需要的所有角色功能!):
然后让保镖管理对文件的访问:
$bouncer->manageAccess($user->getRoles(), substr($_SERVER["PHP_SELF"], 1), "fail.php");
// Any time the user tries to go to a page they don't have access to, they will get to
// fail.php. Any time they try to go to a page that is overridden for them, they will
// get to the overriding page.
如果要仅在用户具有查看权限的情况下显示页面中的内容,只需将其包装为:
if($user->hasRole("Registered User")){
echo "The content";
}
我认为对于您描述的问题,这将是一个很好的解决方案!Hi Goran,感谢您对Zend ACL的建议-我已经仔细阅读了大量Zend文档!但是,由于我们需要实现我们自己的“本机”方法,我尝试寻找Zend ACL如何集成到其他应用程序中的示例o我们可能会借用一些想法…请参阅下面的另一个想法!这看起来非常像ZF acl组件,添加了权限规范,只是您合并了操作和资源。这样,您将无法向资源添加继承,但您似乎不需要,目前我认为是资源-无论如何,继承是一个坏主意。权限看起来很有趣,但却是静态的。例如,它们与特定的规则相关联。我不喜欢的是$this_user==$author_user。如果我正确理解了您的示例,这实际上是一个硬编码规则:如果用户是作者,则允许访问。类似的检查属于acl。谢谢Koen.As我理解这一点,我仍然可以添加继承(因为这是我渴望实现的一个功能),但症结在于您提到的“硬编码”规则-通常,我不介意在代码中粘贴用户流控制(因为它不是严格的授权;更像是身份验证…)但我很想知道你是否知道我该怎么做
$bouncer->manageAccess($user->getRoles(), substr($_SERVER["PHP_SELF"], 1), "fail.php");
// Any time the user tries to go to a page they don't have access to, they will get to
// fail.php. Any time they try to go to a page that is overridden for them, they will
// get to the overriding page.
if($user->hasRole("Registered User")){
echo "The content";
}