【问题标题】:ACL implementation based on variable and not static roles基于变量而非静态角色的 ACL 实现
【发布时间】:2014-08-11 00:53:26
【问题描述】:

我想使用 Zend 的 ACL (Zend\Permissions\Acl) 不仅(仅)基于静态角色,而且还基于(可变)用户点。

在我的应用程序中,每个用户都有积分。资源具有查看它所需的最少点数。对资源的访问应基于用户当前拥有的点数。

示例

资源:

  • 资源 1:20 分
  • 资源 2:100 分
  • 资源 3:150 分

用户:

  • 用户 1:70 分 => 访问资源 1
  • 用户 2:135 分 => 访问资源 1、2
  • 用户 3:170 分 => 访问资源 1、2、3

最好的方法是什么?

到目前为止我的想法

  1. 根据当前登录用户的积分动态创建ACL对象(根据积分设置每个$acl->allow())。这不干净。
  2. 创建一个通用 ACL 并以某种方式传递用户的观点(我设法通过断言来做到这一点。请参阅下面的答案。)
  3. 这里建议了一些(可能更简单/更清洁)的方法...

我将不胜感激朝着正确的方向前进 :)

【问题讨论】:

  • 从存储在数据库中的 def 动态构建 ACL 是很常见的。考虑到这样做的要点也很简单。您可以使用断言来检查点的阈值没问题
  • 有人可以看看我的解决方法吗?

标签: zend-framework zend-framework2 zend-acl


【解决方案1】:

所以这不仅仅是关于 Zend,而是与一般的 ACL 一起工作。

通常,当您在 ACL 中实现访问权限时,您会将其分配给一个组而不是单个用户。然后,您可以轻松(动态地)在组中添加或删除用户。

在 Zend ACL 中,您可以将这些组视为角色。在您的情况下,您将资源的访问权限分配给代表一定数量点的组(或角色)。现在您只需要担心根据他们获得的积分在这些组之间移动用户。

【讨论】:

  • 这是我担心的。不同点/分数的数量非常高,因此我需要做很多设置工作,这对于这样一个简单的任务似乎并不合适(将当前点与所需点进行比较)。这就是为什么我要求一个更优雅的解决方案。说清楚:我已经阅读(并希望理解)关于此的完整文档,但仍然不确定如何去做。
  • @lorey 这是一个常见的误解,认为简单的任务可以快速实施。事实上,它很容易实现,但它通常变得棘手的地方就像你的项目和不同的分数/分数一样。
  • 必须有比这更简单的方法。如果我没记错的话,您是建议将0to25points26to29points30to69points 之类的群组增加到 5000 个?恕我直言,为当前用户创建一个特定的 ACL 对象至少会更容易。纠正我,如果我弄错了......
  • @lorey ACL 对象通常与资源相关联,而不是与用户相关联。如果您将其链接到用户,则需要为每个(新)用户将 ACL 添加到资源中。了解项目的全貌并提出最佳解决方案有点困难。
  • 我知道如果我这样做,我会“弯曲”ACL 概念。这就是为什么我希望有更好的解决方案。我明白这很困难。我希望强硬,有人做了类似的事情并且已经有了一个干净的解决方案:)
【解决方案2】:

好的,我尝试自己实现它。也许它不漂亮,但这是我自己想出的最佳解决方案。这是正确的方向吗?如有任何反馈,我将不胜感激!

解决方案:

我使用我的模型(suggested here)代替字符串作为资源和角色。我使用PointResourceInterface 来标记需要特定点数的资源,并在我的用户类中实现Zend\Permissions\Acl\Role\RoleInterface。现在我创建一个新的NeededPointsAssertion

class NeededPointsAssertion implements AssertionInterface
{
    public function assert(Acl $acl, RoleInterface $role = null, 
            ResourceInterface $resource = null, $privilege = null) {
        // Resource must have points, otherwise not applicable
        if (!($resource instanceof PointResourceInterface)) {
            throw new Exception('Resource is not an PointResourceInterface. NeededPointsAssertion is not applicable.');
        }

        //check if points are high enough, in my app only users have points
        $hasEnoughPoints = false;
        if ($role instanceof User) {
            // role is User and resource is PointResourceInterface
            $hasEnoughPoints = ($role->getPoints() >= $resource->getPoints());
        }

        return $hasEnoughPoints;
    }
}

PointResourceInterface 看起来像这样:

use Zend\Permissions\Acl\Resource\ResourceInterface;

interface PointResourceInterface extends ResourceInterface {
    public function getPoints();
}

设置:

$acl->allow('user', $pointResource, null, new NeededPointsAssertion());

用户可以访问需要积分的资源。但另外检查了NeededPointsAssertion

访问: 我正在检查是否允许这样访问:

$acl->isAllowed($role, $someResource);

如果有用户 $role = $user,否则是 guest 或其他。

灵感来自http://www.aviblock.com/blog/2009/03/19/acl-in-zend-framework/

更新:现在回顾一下,也可以通过构造函数添加所需的点并将其存储为属性。自己决定什么对你的应用有意义...

【讨论】:

    猜你喜欢
    • 2017-12-24
    • 2017-04-08
    • 2014-08-31
    • 2014-04-21
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多