4

我熟悉为我们正在开发的基于 Web 的管理应用程序对用户进行身份验证的一大堆方法,甚至还有各种密切关注授权的技术……

但是,我的问题是,您如何建议我实现一个细粒度的访问控制机制,该机制提供以下内容:

  1. 用户属于“角色”或“组”,例如“销售人员”、“计划”等。
  2. 管理菜单系统仅显示具有与用户角色相关的功能的“页面”
  3. 这些页面中的特定功能有限制 - 例如,在“新预订”页面上,“销售人员”用户可以“仅在未来”发出预订,而在“编辑预订”页面上可以编辑“一周后的预订” '。但是,“计划”用户可能被允许追溯预订“最多一周前”并编辑自己在“任何时间段”进行的预订,但其他人的预订只能“直到明天”......

我知道我可以实现一个基本的基于角色的系统来满足第一...我感觉我应该将整个应用程序分成代码块,每个代码块都有自己的 objectID-permissionID 关系,这样我就可以扫描权限数据库查看哪些对象可用 - 这将有助于我的 2 号。

例如,我如何构建表单控件的任何想法,对于“销售”用户,它只显示未来的日期(但为计划用户显示“一周前”的日期),然后以某种方式将其与中的一行配对POST 解析器检查日期是否实际上在预期范围内?

我已经尝试过将每个代码块保存到数据库中的想法,然后有一个对象表,它根据权限表动态构建代码,这样服务器上唯一的“文件”就是 db 连接文件!

欢迎任何想法...(即使您的背景不是 php/MySQL)


从 Zed Shaw 的 CUSEC 演示文稿中更深入地了解了这个问题,他谈到了“ACL 已死”的原因 - http://vimeo.com/2723800

4

4 回答 4

4

警告,前面有很多 Zend 框架!

您可以使用Zend_AclZend_Navigation轻松处理 1. 和 2 .。

对于数字 3,您将不得不查询模型中的 ACL 对象并手动执行很多操作。您也可以将 Zend Framework 用于表单,并根据用户角色权限包含特定的表单元素验证器。

编辑:

如果您不想走 ZF 路线,您至少可以看看 ZF 是如何处理 ACL 的。

于 2009-10-04T22:58:08.277 回答
2

如果您想构建真正的细粒度访问控制 (FGAC),只需查看我关于此主题的 MySQL 文章:

MySQL 5.0 细粒度访问控制 (FGAC)

基本上,您不希望您的业务代码依赖于 FGAC 实现,您不希望在业务规则语句的where子句中混合 FGAC 代码。select本文展示了避免 SQL 语句混乱的解决方案。

于 2010-08-24T12:14:07.937 回答
1

为了实现“本机”方法,而不是捎带框架,我一直在尝试以下方法。有人会评价这种方法吗?你预见到任何陷阱吗?

// 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...
    }
}

我在正确的轨道上吗?

于 2009-10-05T13:39:34.300 回答
0

我开发了一个名为PHP-Bouncer的库,我认为它可以很好地满足您的需求。它目前支持完全托管的访问,这将允许您在每个页面上使用单个调用(我当然建议使用包含)并在人们无权访问页面时自动重定向,以及自动检索角色一个数据库(如果您使用包含的 MySQL 表设置脚本在数据库中实现角色)。语法非常简单。

您创建保镖:

$bouncer = new Bouncer();

添加您的角色(手动):

// Add a role     Name,      Array of pages role provides
    $bouncer->addRole("Public", array("index.php", "about.php", "fail.php"));
// Add a role          Name,              Array of pages role provides
    $bouncer->addRole("Registered User", array("myaccount.php", "editaccount.php", "viewusers.php"));
// Add a role          Name,   Array of pages role provides       List of pages that are overridden by other pages
    $bouncer->addRole("Admin", array("stats.php", "manageusers.php"), array("viewusers.php" => "manageusers.php"));

或从数据库:

// 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 的类,您的 User 类可以扩展它,它提供了您需要的所有角色功能!):

$user->addRole("Logged In"); // This Role doesn't exist in the bouncer, but we can set it anyways if we feel like setting another flag on the user's account. This can be useful for displaying content in a page only if a user has a secondary role.
$user->addRole("Public");
$user->addRole("Registered User");

然后让 Bouncer 管理对您文件的访问:

$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";
}

我认为对于您描述的问题,这将是一个很好的解决方案!

于 2012-07-28T14:14:33.287 回答