基于变量和非静态角色的ACL实现

时间:2013-05-28 12:16:03

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

我想使用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. 这里建议一些(可能更容易/更清洁)的方式......
  4. 我非常感谢推动正确的方向:)

2 个答案:

答案 0 :(得分:2)

所以这不仅仅是关于Zend,而是一般使用ACL。

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

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

答案 1 :(得分:1)

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

解决方案:

我使用我的模型(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/

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