在遵循本指南之后,我无法获得“更新自己的记录”类型的功能。这是我所拥有的。
管理员和作者角色。作者具有imageUpdateOwn
权限,该权限具有子级的imageUpdate
权限。imageUpdateOwn
权限将isOwner
规则分配给它。所有其他相关/相关代码如下。
数据库
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 action
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]);
当以管理员身份登录时,我会得到每个echo语句的"true“。当以作者身份登录时,我只在图像1000中获得“真”。这告诉我,授权正在按照我创建的isOwner规则返回正确的权限。
但是,当我实际尝试执行update操作时,我甚至无法通过访问控制。我没有得到我在操作中指定的403错误(这正是我所期望的),而是得到了一般的“您不允许执行此操作”错误。这似乎是因为我的默认访问设置要拒绝。如果我将默认访问设置为allow,则可以通过该操作并获得预期的403错误消息。这说明我的行动不允许我通过。
我不确定是否应该在访问控制中列出imageUpdateOwn
角色,但是拥有它不会改变结果(大概是因为imageUpdate
是imageUpdateOwn
的一个子角色,所以通过拥有后者,作者也将拥有前者)。
在上面的内容中,我遗漏了什么,它完全阻止我以作者身份登录时访问更新操作?
编辑1
也许是因为在检查访问控制时没有加载模型,所以无法对created_by用户进行评估。如果是这样的话,我很困惑,因为作者通过imageUpdate
拥有imageUpdateOwn
,它应该允许访问继续。除非它们只在与imageUpdate
相关的规则通过时获得imageUpdateOwn
。在这种情况下,在评估模型之前,作者永远不会“获得”与imageUpdate
角色相关联的访问。这意味着我必须允许所有经过身份验证的用户访问update
操作,并且只在加载模型之后检查操作本身的权限。
发布于 2016-03-22 14:19:21
通过进一步的测试和更多的研究,我发现了(希望有人能证实)。
管理角色被直接分配给imageUpdate
,并且能够更新任何图像。作者被直接分配给imageUpdateOwn
,它以imageUpdate
作为子级。尽管imageUpdate
是已分配权限的子权限,但如果父权限上的规则阻止父权限的授予,则不会给出它。基本上,如果imageUpdateOwn
计算为false (意味着作者用户不是给定图像的所有者),那么作者也不会获得imageUpdate
的子权限。
作者角色不能通过对任何记录的访问控制的原因是,在评估访问控制时,模型不可用。如果模型不可用,附加到imageUpdateOwn
的规则将被计算为false (如果您没有记录,您无法检查它的所有者),这意味着它的子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.');
}
}
这确保不允许未经身份验证的用户在操作附近任何地方进行验证,而通过身份验证的用户必须具有以下内容之一:
imageUpdate
权限(分配给管理角色)。imageUpdateOwn
权限(分配给author角色),如果isOwner
规则的计算结果为true (只有当我们有模型以便检查所有者时,isOwner
权限才能被授予isOwner
权限)。https://stackoverflow.com/questions/36145903
复制相似问题