Php 细粒度访问控制

Php 细粒度访问控制,php,mysql,authorization,access-control,Php,Mysql,Authorization,Access Control,我熟悉我们正在开发的基于web的管理应用程序的一整套验证用户身份的方法,甚至还有各种跟踪授权的技术 但是,我的问题是,您建议我如何实现提供以下功能的细粒度访问控制机制: 用户属于“角色”或“组”,如“销售人员”、“计划”等 管理员菜单系统仅显示具有与用户角色相关功能的“页面” 这些页面中的特定功能有限制-例如,在“新预订”页面上,“销售人员”用户可以“仅在将来”发布预订,“编辑预订”页面上可以“从现在起一周”编辑预订。然而,“规划”用户可能被允许追溯到“一周前”并编辑自己“任何时间段”的预订,但

我熟悉我们正在开发的基于web的管理应用程序的一整套验证用户身份的方法,甚至还有各种跟踪授权的技术

但是,我的问题是,您建议我如何实现提供以下功能的细粒度访问控制机制:

  • 用户属于“角色”或“组”,如“销售人员”、“计划”等
  • 管理员菜单系统仅显示具有与用户角色相关功能的“页面”
  • 这些页面中的特定功能有限制-例如,在“新预订”页面上,“销售人员”用户可以“仅在将来”发布预订,“编辑预订”页面上可以“从现在起一周”编辑预订。然而,“规划”用户可能被允许追溯到“一周前”并编辑自己“任何时间段”的预订,但其他人的预订只能“直到明天”
  • 我知道我可以实现一个基本的基于角色的系统来满足第一。。。我觉得应该将整个应用程序拆分为代码块,每个代码块都有自己的objectID permissionID关系,这样我就可以扫描权限数据库,查看哪些对象可用——这将有助于我解决第二个问题

    有没有想过如何构建表单控件,例如,对于“销售”用户,表单控件只显示未来的日期(但对于计划用户,则显示“一周前”的日期),然后在POST解析器中将其与检查日期是否在预期范围内的行配对

    我一直在考虑应该将每个代码块保存到数据库中,然后创建一个对象表,根据权限表动态构建代码,这样服务器上唯一的“文件”就是db连接文件

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


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