Yii2 AccessControl和RBAC更新自己的记录

时间:2016-03-22 04:05:57

标签: php yii2

关注this guide后,我无法获得更新自己的记录"工作的功能类型。这就是我所拥有的。

管理员和作者角色。作者拥有imageUpdateOwn权限,其作为孩子具有imageUpdate权限。 imageUpdateOwn权限已分配isOwner规则。所有其他相关/相关代码如下。

数据库

database

OwnerRule.php

Image模型具有created_by属性,该属性是记录的所有者。

public function execute($user, $item, $params)
{
    return isset($params['model']) ? $params['model']->created_by == $user : false;
}

ImageController.php AccessControl

public function behaviors()
{
    return [
        'access' => [
            'class' => AccessControl::className(),
            'rules' => [
                [
                    'allow' => true,
                    'actions' => ['update'],
                    'roles' => ['imageUpdate'],
                ],
                [
                    'allow' => true,
                    'actions' => ['delete'],
                    'roles' => ['imageDelete'],
                ],
                [
                    'allow' => true,
                    'actions' => ['index', 'view', 'create'],
                    'roles' => ['@'],
                ],
                [
                    'allow' => false,
                ],
            ],
        ],
    ];
}

ImageController.php操作

public function actionUpdate($id)
{
    $model = $this->findModel($id);

    if (\Yii::$app->user->can('imageUpdate', ['model' => $model])) {
        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->redirect(['view', 'id' => $model->id]);
        } else {
            return $this->render('update', [
                'model' => $model,
            ]);
        }
    } else {
        throw new HttpException(403, 'You do not have permission to update this record.');
    }
}

在我的测试中,我以作者身份登录并上传了图像1000,然后以管理员和上传的图像1001登录。在每个用户登录时执行以下快速测试,产生预期结果。

$image1000 = \app\models\Image::findOne(1000); // author uploaded
$image1001 = \app\models\Image::findOne(1001); // admin uploaded

echo \Yii::$app->user->can('imageUpdate', ['model' => $image1000]) . "<br>";
echo \Yii::$app->user->can('imageUpdate', ['model' => $image1001]);

以管理员身份登录时,我得到&#34; true&#34;对于每个echo语句。以作者身份登录后,我得到了#34; true&#34;仅对于图像1000.这告诉我授权使用我创建的isOwner规则按预期返回正确的权限。

然而,当我尝试实际进行更新操作时,我甚至无法通过访问控制。而不是获得我在动作中指定的403错误(这是我期望的)我获得了通用&#34;您不被允许执行此操作&#34;错误。这似乎是因为我将默认访问权限设置为拒绝。如果我将默认访问权限设置为允许,我可以完成操作并获得预期的403错误消息。这告诉我行动不允许我通过。

我不确定imageUpdateOwn角色是否应该在访问控制中列出但是在那里没有更改结果(可能是因为imageUpdateimageUpdateOwn的孩子所以拥有后者,作者也将拥有前者。

我在上面所遗漏的是完全阻止我以作者身份登录时访问更新操作?

修改1

也许是因为在检查访问控制时没有加载模型,因此无法评估created_by用户。如果是这种情况,我很困惑,因为作者imageUpdate通过imageUpdateOwn它应该允许继续访问。除非他们仅在与imageUpdate相关联的规则通过时获得imageUpdateOwn。在这种情况下,作者永远不会得到&#34;与imageUpdate角色关联的访问权限,直到可以评估模型。这意味着我必须允许所有经过身份验证的用户访问update操作,并且只有在加载模型后才检查操作本身内部的权限。

1 个答案:

答案 0 :(得分:1)

通过进一步的测试和更多的研究,我发现了这一点(希望有人可以证实)。

管理员角色直接分配imageUpdate,可以更新任何图片。作者直接分配imageUpdateOwn,其中imageUpdate为孩子。虽然imageUpdate是已分配权限的子项,但如果父项上的规则阻止了父项的授予,则不会给出它。基本上,如果imageUpdateOwn的计算结果为false(意味着作者用户不是给定图像的所有者),则作者将不会获得imageUpdate的子权限。

作者角色未通过任何记录的访问控制的原因是因为在评估访问控制时,该模型不可用。如果该模型不可用,则imageUpdateOwn附带的规则将评估为假(如果您没有记录,则无法检查其所有者),这意味着其子imageUpdate也不会给予许可。

解决方案是允许所有经过身份验证的用户通过访问控制,然后检查操作本身的特定权限,如下所示:

public function behaviors()
{
    return [
        'access' => [
            'class' => AccessControl::className(),
            'rules' => [
                [
                    'allow' => true,
                    'roles' => ['@'],
                ],
            ],
        ],
    ];
}
...
public function actionUpdate($id)
{
    $model = $this->findModel($id);

    if (\Yii::$app->user->can('imageUpdate', ['model' => $model])) {
        // Save the record and redirect the user
    } else {
        throw new HttpException(403, 'You do not have permission to update this record.');
    }
}

这可确保在经过身份验证的用户必须具有以下某项之一时,不允许未经身份验证的用户访问该操作:

  1. imageUpdate权限(分配给管理员角色)。
  2. imageUpdateOwn权限(分配给作者角色),如果imageUpdate规则评估为true,则会赋予isOwner权限(如果我们有模型,则只能评估为true)所以可以检查所有者)。
相关问题