细粒度的访问控制

发布于 2024-08-06 04:12:00 字数 857 浏览 1 评论 0 原文

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

但是,我向您提出的问题是,您会如何推荐我实施细粒度的访问控制机制,提供以下功能:

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

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

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

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

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


Zed Shaw 在 CUSEC 演示中谈论为什么“ACL 已死”,可以更深入地了解该问题 - http://vimeo.com/2723800

I'm familiar with a whole bunch of ways to authenticate users for the web-based administration application we're developing, and even various techniques to keep tabs on authorisation...

However, my question to you is, how would you recommend I implement a fine-grained access control mechanism that offers the following:

  1. Users belong to 'roles' or 'groups' such as 'salesperson', 'planning', etc.
  2. The admin menu system shows only 'pages' which have functions relevant to the users role(s)
  3. Specfic functions within those pages have constraints - for example, on the 'new booking' page, 'salesperson' users can issue a booking 'only in the future', and on the 'edit bookings' page can edit bookings 'one week from now'. However, 'planning' users might be allowed to retrospectively book 'up to one week ago' and edit bookings made by themselves for 'any time period', but bookings made by others only 'up until tomorrow'...

I know I can implement a basic role-based system to satisfy no.1... I have a feeling I should split the entire application into code chunks, each with their own objectID-permissionID relationship so that I can scan the database of permissions to see which objects are available - that would help me with no.2.

Any ideas how I might build the form control for example, which for 'sales' users only displays a date in the future (but displays dates up to 'one week ago' for planning users), then somehow pairing that with a line in the POST parser that checks to see if the date is in fact within the expected range?

I've played around with the idea I should save each code chunk to the database, then have an object table which dynamically builds the code according to the permissions table, so that the only 'file' on the server is the db connection file!

Any ideas welcome... (even if your background isn't php/MySQL)


Some more insight into the problem from a CUSEC presentation by Zed Shaw talking about why "the ACL is dead" - http://vimeo.com/2723800

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

安穩 2024-08-13 04:12:00

警告,前面有很多 Zend Framework!

您可以使用 Zend_AclZend_Navigation .

对于第三点,您将必须查询模型中的 ACL 对象并手动执行大量操作。您也可以将 Zend Framework 用于表单,并根据用户角色权限包含特定的表单元素验证器。

编辑:

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

Warning, a lot of Zend Framework ahead!

You can easily handle 1. and 2. with Zend_Acl and Zend_Navigation .

For number 3 you will have to query the ACL object in your model and do a lot of stuff by hand. You could utilize Zend Framework for the forms as well and include specific form element validators depending on the users role permission.

EDIT:

If you do not feel like going the ZF route you can at least take a look at how the ACL is handled in ZF.

时光清浅 2024-08-13 04:12:00

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

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

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

If you want to build real fine-grained access control (FGAC), just check my article on this subject for MySQL :

MySQL 5.0 Fine-Grained Access Control (FGAC)

Basically, you don't want your business code be dependent on the FGAC implementation, you don't want to mix FGAC code in where clause of the select statements of your business rules.
This article shows solutions to avoid cluttering of SQL statements.

痴者 2024-08-13 04:12:00

为了实现“原生”​​方法,而不是依赖框架,我一直在尝试以下方法。有人会评价这种方法吗?您预见到任何陷阱吗?

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

我在正确的轨道上吗?

In a bid to implememt a 'native' approach, rather than piggy-backing a framework, I've been playing around with the following. Would anyone rate this approach? Do you foresee any pitfalls?

// Check database for existence of this $user against this $object.
function get_permission($user, $object){
    // Query goes here...
    if( ... ){
        return $permission;
    } else {
        return FALSE;
    }
}

The above function would query the database and output something like this:

// 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'  

The following code in the page containing the form input:

// 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']);
}

After the booking has been made, another page allows us to edit that field:

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

Am I on the rigt track?

贱贱哒 2024-08-13 04:12:00

我开发了一个名为 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";
}

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

I developed a library called PHP-Bouncer that I think would meet your needs very well. It currently supports fully managed access which will allow you to use a single call on every page (I recommend using an include of course) and automatically redirect people if they don't have access to a page, as well as automatic retrieval of roles from a database (if you implement the roles in the DB using the included MySQL table setup script). The syntax is pretty simple.

You create the bouncer:

$bouncer = new Bouncer();

Add your roles (manually):

// 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"));

or from the Database:

// 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");

Add a user and give them some roles (Note: There is a class called BouncerUser which your User class can extend, it provides all of the role functionality you need!):

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

Then let the Bouncer manage access to your files:

$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 you want to show content in a page only if a user has permission to view it, simply wrap it in:

if($user->hasRole("Registered User")){
    echo "The content";
}

I think for the problem you described this would be a great solution!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文