这个问题是在为自定义应用程序设计专用ACL系统时出现的,但我认为它适用于一般的ACL系统,因为我还没有找到如何通过查看一些主流系统来解决这个问题,比如Zend_ACL
。
在我的应用程序中,权限是动态授予的,例如:用户获得某个活动的查看权限,因为他是该活动所链接到的团队的成员。这是建立在这样的假设之上:您总是有一个想要在Item
(我的应用程序中的一个对象,例如Activity、Team等)上执行操作(查看/编辑等)的Employee
(用户)。这对于我的目标使用来说已经足够了;
$Activity = new Activity( $_POST['activity_id'] );
$Acl = new Acl( $Activity );
if ( !$Acl->check( 'edit' ) {
throw new AclException('no permission to edit');
}
我的Acl
类包含授予权限的所有业务规则,它们是“动态”创建的(尽管出于性能原因有时会进行缓存);
/**
* Check the permissions on a given activity.
* @param Activity $Activity
* @param int $permission (optional) check for a specific permission
* @return mixed integer containing all the permissions, or a bool when $permission is set
*/
public function checkActivity( Activity $Activity, $permission = null ) {
$permissions = 0;
if ( $Activity->owner_actor_id == $this->Employee->employee_id ) {
$permissions |= $this->activity['view'];
$permissions |= $this->activity['remove'];
$permissions |= $this->activity['edit'];
} elseif ( in_array( $this->Employee->employee_id, $Activity->contributor_ids_arr ) ) {
$permissions |= $this->activity['view'];
} else {
/**
* Logged in user is not the owner of the activity, he can contribute
* if he's in the team the activity is linked to
*/
if ( $Activity->getTeam()->isMember( $this->Employee ) ) {
$permissions |= $this->activity['view'];
}
}
return ( $permission ? ( ( $permission & $permissions ) === $permission ) : $permissions );
}
此系统按原样运行良好。
当您想要“颠倒”ACL规则时,这种方法就会出现问题。例如,“获取我被允许编辑的所有活动”。我不想在需要活动的代码中放入任何像WHERE owner_actor_id = $Employee->employee_id
这样的逻辑,因为这是Acl
类的职责,应该保持集中化。在当前的实现中,我没有其他选择来获取代码中的所有活动,然后逐个断言它们。这当然是一种非常低效的方法。
因此,我正在寻找一些关于良好架构的想法(或者指向现有ACL实现或一些相关设计模式的指针),以创建一个可以以某种方式同时执行hasPermission( $Item, $permission )
和fetchAllItems( $permission )
的ACL系统,理想情况下使用相同的业务规则集。
提前感谢大家!
我已经研究了Zend_ACL
实现,但它更侧重于一般权限。我还在SO上发现了以下问题:
但不幸的是,他们似乎也没有回答这个问题。
发布于 2011-09-16 15:56:28
一位同事向我提供了另一种观点,这也可能是解决这个问题的方法。
我认为我想要的是将所有与访问相关的代码放在ACL类中(这反映了我的说法:“我不想在需要活动的代码中放入任何像WHERE owner_actor_id = $Employee->employee_id
这样的逻辑,因为这是Acl类的职责,应该保持集中。”)。
我真正想要的是,确保用户永远不能访问,这不符合ACL类中列出的规则。如果“worker code”已经获取了数据的一个子集,那么这并不是什么问题--只要最终根据“真正的”ACL进行检查即可。最糟糕的情况是用户看到的比他应该看到的要少,这比看到更多要好得多。
使用这种“解决方案”(如果您愿意,可以选择另一种方法),您可以避免获取所有数据,同时保持将所有规则放在一个位置的好处。我能想到的任何其他解决方案都会涉及到规则的复制,因为您需要使用PHP中的规则来检查给定的资源,并且需要用MySQL编写的规则来获取所有资源。
顺便说一句,仍然可以将子集获取代码放在Acl
类中--但是我认为保持类的小巧和集中会更好(因为我认为该类中代码的可读性也非常重要)。
发布于 2011-09-22 08:55:08
您可能想回顾一下解决此问题的cakephp方法:
http://book.cakephp.org/view/1543/Simple-Acl-controlled-Application
发布于 2011-09-22 21:09:00
据我所知,应该使用ACL来检查一般权限。基于实体的权限不应为ACL的主题。对于这样的任务,我将看看Linux/Unix是如何管理文件权限的。
owner group all
read 1 1 1
write 1 0 0
execute 1 0 0
--------------------------------------
7 4 4
使用类似的实现,获取和检查权限都很容易,但您需要在应用程序中再添加一层。
编辑:这个架构将尊重单一责任原则,因为检查“用户是否被允许打开页面”不同于“用户将在页面上看到什么”。
https://stackoverflow.com/questions/7403104
复制相似问题