【问题标题】:How to limit data to users who own it without limiting admin users in CakePHP?如何将数据限制为拥有它的用户而不限制 CakePHP 中的管理员用户?
【发布时间】:2010-06-12 21:45:35
【问题描述】:

目前我正在编写一个有多个用户的应用程序。他们的数据应该只对他们可见,而不是系统中其他经过身份验证的用户可见。我还有管理系统并有权访问所有信息的管理员。在不限制管理员用户的情况下限制用户访问其数据的最佳方法是什么?

目前我正在使用回调来限制用户的查询,但管理员将获得相同的限制。所以我需要知道一个更好的方法来做到这一点。更重要的是,正确的方法。

例如,我希望标准用户只能看到他们的用户信息,并且仅限于对他们的信息进行 CRUD 操作。但是,管理员应该能够看到所有用户和 CRUD ALL 用户数据。有什么想法吗?

【问题讨论】:

  • 我投票决定将此问题作为题外话结束,因为解决方案的内容不再可用。
  • 我添加了一个可能有用的新解决方案。仅仅因为解决方案不可用并不意味着这是“离题”。

标签: cakephp cakephp-1.3


【解决方案1】:

你需要:

  • 有关当前用户的信息
  • 有关商品的信息

你将它们与这样的东西结合起来(简单的例子):

$user = $this->Auth->user();
$book = $this->Book->find(…);
if ($user['type'] != 'admin' && $user['id'] != $book['Book']['creator_id']) {
    $this->Session->setFlash("You're not allowed to view this item");
    $this->redirect('somewhere');
}

你可以在你的模型中创建一个方法

function userCanAccessItem($item, $user)

集中访问检查的逻辑并从您的控制器调用它。

更好的是,如果您使用的是 Cake 的 admin routing,您可以省略所有在 admin_ 操作中的检查,而只在用户可访问的操作中应用普通用户访问权限检查。

您可能还想查看ACLs 以获得更细粒度的访问控制。

【讨论】:

  • 感谢您的回复。这类似于已经提供的另一个答案。但同样,['type'] 没有使用 Auth 设置。是我需要在某处手动执行还是需要覆盖?我正在使用管理员路由,这就是我遇到困难的原因。例如,如果我在模型中放置一个回调(这似乎是最好的方法,因为它可以在全局范围内完成),那么同样的限制也将适用于管理员。这似乎仍然不是最明显的“蛋糕”方式。
  • @cdburgess 我相信$this->Auth->user() 的信息只是简单地存储在$this->Session->read('Auth') 中。您可以在登录时在此处编写解析用户类型所需的任何其他信息。您不应该将用户身份验证放在模型回调中,因为这会严重限制模型的灵活性。身份验证是在控制器中完成的。
  • 我们可以使用 ACL 进行行级访问控制吗?
【解决方案2】:

您可以获取当前用户信息this way:$this->Auth->user()。您可以在回调中使用用户组 ID 来限制查询。也可以在WhoDidIt Behavior 进行战利品。

【讨论】:

  • 这似乎是一种“全局用户”方法。我的 ADMIN 用户在 $this->Auth 中与 STANDARD 用户相同。但该组并不总是在数据中。例如,如果我有一个用户添加书籍,组 ID 将不会出现在 BOOK 表中。但是每个用户应该只能查看他们的书籍。管理员应该能够查看所有书籍。我不确定你分享的内容是否会起作用。我不需要按用户跟踪更新,我需要限制可以访问的数据。
  • 如果您将使用 WhoDidIt 行为,您将在 BOOK 表的 created_by 列中拥有用户 ID(创建记录的人)。如果用户已登录,$this->Auth->user() 中应该有用户 ID 和组 ID。如果$this->Auth->user('id')created_by 相同或$this->Auth->user('group_id') 为'admin' 则允许记录。
【解决方案3】:

对于任何来到这里的其他人,这就是我的设置方式。

首先我设置了一个basic Role based ACL

然后我拒绝普通用户访问reports/all

$config['rules']['deny'][reports/all'] = 'Role/default' ;

然后在我想保护的模型中添加了这个:

public function beforeFind($queryData){
    //TODO:make this cleaner
    App::uses('ComponentCollection', 'Controller');
    App::uses('AclComponent', 'Controller/Component');
    $collection = new ComponentCollection();
    $this->Acl = new AclComponent($collection);     

    if(!$this->Acl->check(array('User'=>AuthComponent::user()),'/reports/all/')){  // must be a user (not admin)
        $this->bindModel(array('hasOne' => array('ReportsUser')));
        $queryData['conditions']['ReportsUser.user_id'] = AuthComponent::user('id');
        $queryData['recursive'] = 2;
    }
    return $queryData;
}

在 ACL 不允许访问 reports/all 的情况下,我们会向任何查找查询添加一个条件,以便它只显示具有正确 user_id 的报告。

【讨论】:

  • 这很糟糕,原因有两个:首先在模型中使用组件,其次更重要的是 - (db)acl 是一个非常糟糕的选择来解决“如何将数据限制为拥有它的用户,而不限制管理员用户”。如果原因不明显,请考虑一百万用户和一百万产品需要存在多少 aro、aco 和权限记录 - 以表达 一个 规则。
  • 首先,就像我在其他地方所说的那样,除了 ACLComponent 之外,没有其他方法可以从模型访问 ACL 信息。其次,您似乎错过了我建议使用基于角色的 ACL,然后您只有 2 个 ARO,“admin”和“user”,然后您只有 1 个 ACO Reports/all。另外我不推荐db acl,而是phpAcl。显然你可以只做if (AuthComponent::user('role')=='admin')...,但如果你有管理员用户,你可能需要其他 ACL 类型的活动。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-24
  • 2019-08-11
  • 1970-01-01
  • 2013-12-25
  • 2017-11-15
  • 1970-01-01
相关资源
最近更新 更多