CakePHP - 限制只能编辑自己的“数据”

4

目前我使用Auth组件让用户登录/退出 - ACL被定义为对用户组进行排序(Guests,Users,Admins)- 具有明显的限制;管理员可以访问所有内容,用户只能在用户控制器中编辑,而访客只能看到显示/索引/查看等等。

现在为了防止用户编辑其他用户 - 我有一个名为isOwner()的函数,它基本上检查您是否正在尝试编辑自己的个人资料;还检查是否是管理员正在编辑。如果用户是他们要编辑的内容的所有者,则允许它,否则它将重定向并显示闪存消息。

阅读http://book.cakephp.org/view/1245/Defining-Permissions-Cake-s-Database-ACL后 - 我想知道是否可以在ACL中定义此功能?

类似于:

$this->Acl->allow(array('model' => 'User', 'foreign_key' => $id), 'Users', 'edit', $id) 

虽然我还没有深入研究,但我假设我需要为每个新注册的用户创建一些sort of beforeSave()来允许他编辑自己的个人资料。


并不是 - 我实际上想要使用 ACO_ARO 的权限,而不是放弃它。 - Shaz MJ
1
嗨Shaz,用户如何获得访问另一个配置文件的权限?用户/编辑操作不应该带有ID参数,它应该始终假定当前请求进行操作的是已登录用户的ID。我是否遗漏了什么? - Jonah
使用脚手架/烘焙 - $id 作为表单中的参数进行传递,并且还作为 URL 参数给出(user/edit/id)。您可以通过浏览到 user/edit/anotherid 轻松覆盖它 - 并保存它,除非您检查 $id 是否与 URL、表单和经过身份验证的会话中的匹配。如果我还想让管理员能够编辑用户-如果所有操作都在 ACL 中完成,而无需在控制器中担心它,那就更容易了。 - Shaz MJ
ACL已经为组执行数据库查找以确保访问权限;我认为它不会给每个用户增加太多开销。此外,我将会话存储在数据库中,因此我相信它实际上会加速事情的进行。此外,我有17个控制器/模型,每个模型都有超过两打方法 - 所以我不得不写if(isAdmin() || isOwner()){can edit}等太多次 - 如果没有测试,我几分钟内就会迷失在我已经/没有设置正确权限的问题上。我不认为ACL算作数据层?它只是保护数据的访问层。 - Shaz MJ
“你不应该把业务逻辑放在数据层。”这是一个有趣的观点。然而,CakePHP概述页面则表示:“模型层代表了应用程序实现业务逻辑的部分。它负责检索数据并将其转换为应用程序的有意义的概念。这包括处理、验证、关联或其他与处理数据相关的任务。”我认为,当你使用Cake时,暗示着你遵循MVC模式。 - Stijn de Witt
显示剩余4条评论
2个回答

2
我已决定将此作为答案发布,因为它包含代码示例。
您可以创建一个组件(或函数),并在 app_controller 中使用 beforeFilter() 回调,这样您就不需要手动将该函数添加到所有控制器中。
此外,您可以为操作使用多个前缀(参见核心中的 Routing.prefixes),这将更容易地控制访问。例如:

[app_controller.php]

function beforeFilter() {
    if(isset($this->params['prefix']) && $this->params['prefix'] == 'admin'){
         if(!isAdmin() || !isOwner())
             $this->cakeError('error404');
    }
}

[users_controller.php]

  function admin_edit($id = null){
        ... // edit as usual
    }

在 LAMP 栈中,通常瓶颈出现在数据库中。我的问题是 CakePHP 产生的查询数量过多。曾经我发现我的“联系我们”页面需要进行 21 次查询才能检索到数据结构以及此公共页面的权限。只有当权限是动态的时候,即“用户 #29 可以编辑用户 #12,因为管理员在后台决定了它”,才可以合理地使用 ACL 访问数据。但是,如果您对访问数据的规则是静态的(例如,“用户只能编辑自己的信息,管理员可以编辑所有内容”),那么当您已经知道答案时执行查询就有点毫无意义,因为这些规则不会随时间而改变。所以这完全取决于您的应用程序。最后,一个最后的想法,如果你仍然计划执行更多的查询 =P,你可以设置 Auth 组件的授权方法。但是,对我来说,使用 ACL 组件似乎是一个坏主意。祝贺!

不同于我想要的,但仍然是一个非常好的替代方案,谢谢! - Shaz MJ

0

好的,虽然已经过去了将近4年,但对于像我一样在研究CakePHP应用程序的Acl解决方案时偶然发现这篇文章的人来说,简短的答案是可以的,但必须仔细规划。如果您确实需要这种级别的身份验证,那么没有比Cake的ACL实现更可行的替代方案,至少是可靠的(不进行批评...)。请注意,当前稳定版本为2.4:

本质上,解决方案是在您的代码中用$dbAcl->check($user, $entity, $action);替换isOwner()调用,该方法在您的ACL数据库结构上进行查找 - 请参见http://api.cakephp.org/2.4/class-DbAcl.html

当然,还有更多要考虑的。CakePHP并没有为此类身份验证提供开箱即用的解决方案。它提供了一个工具包,供您使用以构建一个:

  • 用于查询ACL数据库结构的DbAcl。
  • AclBehavior。您想要在实体级别上应用授权的类对象的模型应加载Acl行为。这将自动创建和删除对象级别的ACO / ARO,并处理所有内容。请参见http://api.cakephp.org/2.4/class-AclBehavior.html
  • 使用Controller :: isAuthorized()进行控制器级别的授权。这是您将调用dbAcl :: check()的地方。请参见http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#authorization。如果您真的想要,也可以从自定义授权模块中执行此操作。
  • 您仍然需要使用CRUD或Action Authorize组件来补充此功能。重要的是要意识到,在默认的CakePHP烘焙控制器中,有两个隐式子类的操作/端点。那些对控制器本身进行操作的操作(add,index)和那些对由控制器表示的对象类别的实体进行操作的操作(edit,view,delete)。这类似于类与实例方法。所述类型的授权仅适用于作用于实体的终点。您可以回退到Action / Crud auth以获取其余部分。
  • 显然,您需要一个用户模型..

请注意,Cake文档结尾处有两个关于ACL的好教程 - http://book.cakephp.org/2.0/en/tutorials-and-examples。它们没有明确涵盖此类设置,但是只要您理解了涵盖的概念并掌握dBAcl,就应该能找到自己的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接