首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >构建“双向”OO动态ACL系统

构建“双向”OO动态ACL系统
EN

Stack Overflow用户
提问于 2011-09-13 21:57:47
回答 4查看 1.7K关注 0票数 16

这个问题是在为自定义应用程序设计专用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上发现了以下问题:

但不幸的是,他们似乎也没有回答这个问题。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-09-16 15:56:28

一位同事向我提供了另一种观点,这也可能是解决这个问题的方法。

我认为我想要的是将所有与访问相关的代码放在ACL类中(这反映了我的说法:“我不想在需要活动的代码中放入任何像WHERE owner_actor_id = $Employee->employee_id这样的逻辑,因为这是Acl类的职责,应该保持集中。”)。

我真正想要的是,确保用户永远不能访问,这不符合ACL类中列出的规则。如果“worker code”已经获取了数据的一个子集,那么这并不是什么问题--只要最终根据“真正的”ACL进行检查即可。最糟糕的情况是用户看到的比他应该看到的要少,这比看到更多要好得多。

使用这种“解决方案”(如果您愿意,可以选择另一种方法),您可以避免获取所有数据,同时保持将所有规则放在一个位置的好处。我能想到的任何其他解决方案都会涉及到规则的复制,因为您需要使用PHP中的规则来检查给定的资源,并且需要用MySQL编写的规则来获取所有资源。

顺便说一句,仍然可以将子集获取代码放在Acl类中--但是我认为保持类的小巧和集中会更好(因为我认为该类中代码的可读性也非常重要)。

票数 1
EN

Stack Overflow用户

发布于 2011-09-22 08:55:08

您可能想回顾一下解决此问题的cakephp方法:

http://book.cakephp.org/view/1543/Simple-Acl-controlled-Application

票数 0
EN

Stack Overflow用户

发布于 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

使用类似的实现,获取和检查权限都很容易,但您需要在应用程序中再添加一层。

编辑:这个架构将尊重单一责任原则,因为检查“用户是否被允许打开页面”不同于“用户将在页面上看到什么”。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7403104

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档