Yii RBAC:访问特定项目/行

时间:2014-05-11 01:32:52

标签: php sql yii access-control rbac

我有一个用例,我需要为用户分配编辑高动态项目的权限,这些项目可以是数百或数千。属于同一类型或组的每个用户必须分配给其中一些项目(并且不同的用户可以访问相同的公司项目)。此外,这些物品可以迅速增加或消失。这些项目与用户没有内在关系,但必须任意分配给用户。

让我们将这些项目称为公司项目

因此,我希望能够为用户分配公司项目,并动态撤销该访问权限。然后在控制器内部使用这些分配来检查某些操作是否可以继续...... 从概念上讲,问题始终是相同的:测试用户是否有权访问表格中的特定项目/行,公司项目'表。

我的想法是使用yii RBAC system,同时尝试保持授权树静态,从而避免每次公司项目时创建/删除角色或任务已创建或删除。相反,我想知道我是否可以使用$data中的assign($itemName, $userId, $bizRule, $data)参数和类似于以下内容的树来执行此操作:

  • adminUser :角色
    • companyAdmin :角色
      • editCompanyItemRole bizrule 的角色; bizrule 只需检查$params['companyItemId']内是否存在$data['companyItemsAllowed'],即可测试对公司条目的访问权限。在分配时,应该收到一个$data,其中包含一系列公司项目'ID,用户应该被允许编辑!
        • editItem :操作;用于检查控制器中的访问权限,并且应提供公司项 ID,并希望检查用户,例如Yii::app()->user->checkAccess('editItem', array('companyItemId' => 666));

这样,每当我们需要将用户分配更改为公司项目时,我们唯一需要做的就是更改原始分配中的$data['companyItemsAllowed']数组。 角色总是一样的!

问题:

  1. 这个系统是否有效,我能否以这种方式使用Yii的RBAC系统 ??
  2. 这是完成要求的理想方式,假设我们有数千个公司项目,我们可能会为每个用户分配数十个 ?? 为什么 ...

3 个答案:

答案 0 :(得分:1)

您可以在其访问控制实现中使用Yii的数据所有者概念。

在您自己的应用程序中实现此操作的第一步是指示控制器启用此规则。这是通过覆盖filters()函数来完成的。

class ContentController extends Controller {

    public function filters() {
        return array(
            'accessControl'
        );
    }

    public function accessRules() {
    }
}

' accessControl' flag指定访问控制应用于数据管理。实际业务规则在accessRules()函数中定义,并指定将被评估以提供所需控件的访问控制表达式。函数实现的例子是。

public function accessRules() {
    return array(
        array('allow', // allow all users to perform 'index' and 'view' actions
            'actions' => array('view'),
            'users' => array('*'),
        ),
        array('allow', // allow authenticated user to perform 'add' action
            'actions' => array('add'),
            'users' => array('@'),
        ),
        array('allow', // allow only the owner to perform 'modify' 'delete' actions
            'actions' => array('modify', 'delete'),
            'expression' => array('ContentController','isMyRecord')
        ),
        array('deny', // deny all users
            'users' => array('*'),
        ),
    );
}

isMyRecord是一个将运行的方法,返回true或false以指示是否应该允许该操作。

public function isMyRecord(){

    if (Yii::app()->user->checkAccess( ...))
       return true;
    else
       return false;
}

答案 1 :(得分:1)

I wrote a small framework用于访问控制。它简单,小巧轻便。我的动机是将应用程序的访问控制与其他框架分离,因为我认为来自其他框架的访问控制与框架样式非常相关。

例如在Yii中你必须在控制器中对它进行编程,我不喜欢它,因为当你添加一个新的动作(from Yii Wiki)时,是非常无聊的程序新规则:

class PostController extends CController
{

    public function accessRules()
    {
        return array(
            array('deny',
                'actions' => array('create', 'edit'),
                'users' => array('?'),
            ),
            array('allow',
                'actions' => array('delete'),
                'roles' => array('admin'),
            ),
            array('deny',
                'actions' => array('delete'),
                'users' => array('*'),
            ),
        );
    }

}
恕我直言,必须动态完成。您应该能够在其管理系统中直观地编写规则,然后开发人员适当地编写操作和模型,然后就绪。

要将我的库与Yii应用程序集成,我使用import,例如:

$path = Yii::getPathOfAlias('application.services.RapidAuthorization');
Yii::setPathOfAlias('RapidAuthorization', $path);

我使用模块中的beforeControllerAction()进行整合。

当我有时间时,我会为多个框架编写手动集成,首先我有Yii,Zend和Symfony的经验。并将文档翻译成英文。但现在代码是英文。

我希望至少能让您了解如何编写访问控制。

答案 2 :(得分:0)

我决定采用以下方法,在决定只在$data['companyItemsAllowed']内维护公司项目数组 时,最好满足这些要求:< / p>

  • UsersCompanyItems之间创建了一个关联表;称之为association_table;
  • 创建了RBAC树,如问题所示,但bizRule如下所示:

    $ret = Yii::app()->dbConnection->createCommand('SELECT EXISTS(SELECT 1 FROM `association_table` WHERE user_id=:userId AND company_item_id=:companyItemId)')
    ->queryScalar(array(':userId' => $params['userId'], 'companyItemId' => $params['companyItemId']));
    return $ret;
    

这允许我维护访问控制界面,如下所示:

    Yii::app()->user->checkAccess('editItem', array('companyItemId' => 666));

(回想一下我们不需要来传递userId数组上的$params !.

当然,这会将公司项目的实际权限分配与 RBAC 系统分开:我将editCompanyItemRole分配给一些用户使用Yii提供的RBAC机制,但每个实际项目必须通过在association_table上插入一行来单独分配...

所以,尽管首先考虑在$data内部维护一系列公司项目可能会有效,但我认为这是最好的,也更灵活。此外,关于bizRule的一般想法似乎也有效。