我正在尝试使用 Yii 构建一个站点,并发现自己处于需要对 Yii 中的访问控制隐喻进行一些澄清的情况。具体来说,可以覆盖 accessRules CController
的后代中的方法。
先决条件:
这是 Gii 默认生成的代码,与 documentation 非常相似:
public function accessRules()
{
return array(
array('allow', // allow all users to perform 'index' and 'view' actions
'actions'=>array('index','view'),
'users'=>array('*'),
),
array('allow', // allow authenticated user to perform 'create' and 'update' actions
'actions'=>array('create','update'),
'users'=>array('@'),
),
array('allow', // allow admin user to perform 'admin' and 'delete' actions
'actions'=>array('admin','delete'),
'roles'=> array('admin'),
),
array('deny', // deny all users
'users'=>array('*'),
),
);
}
问题:
我不清楚的是 - 为什么我们需要为许多不同的用户和组以及不同的操作定义访问规则,而不是仅检查一个当前用户和操作的权限? ——这里用斜体突出显示了我的主要问题,以防读者(答案作者)不太清楚。
此代码在特定请求的上下文中执行,针对该请求,特定 Controller
、特定操作
和特定用户
已知。例如,如果用户是访客,我认为没有任何理由为“管理员”角色或经过身份验证的用户定义规则。
推理:
经过一番阐述,我得出了以下实现:
public function accessRules()
{
return array(
array(Yii::app()->user->hasRights()?'allow':'deny'),
);
}
其中 hasRights
是添加到 CWebUser
后代中的简单自定义方法:
class WebUser extends CWebUser
{
private $ACL = // ACL example
array('user' => // controller id
array('index' => User::AC_MODERATOR, // action ids
'view' => User::AC_MODERATOR,
'create' => User::AC_MODERATOR,
'update' => User::AC_ADMIN,
'delete' => User::AC_ADMIN,
'admin' => User::AC_ADMIN),
// ...
);
public function hasRights()
{
return (Yii::app()->user->getState('accessRights') >=
$this->ACL[Yii::app()->controller->id][Yii::app()->controller->action->id]);
}
}
正如您所见,hasRights
使用当前用户“权限”(照常从数据库读取)、当前 Controller 和操作来计算单个 bool 值 true
或 false
值作为访问决策。
这种方法有什么问题吗?为什么 Yii 默认不使用这样简单的东西?
上面 Gii 生成的 accessRules
不仅看起来过多,而且还意味着访问规则分散在许多 Controller 中。在我的方法中,使用单一且紧凑的 ACL。
最佳答案
这就是我认为你感到困惑的地方。
首先,Yii 实际上只查看当前用户和当前操作。就像您通过获取由 Controller ID 索引的嵌套数组来获取 Controller 的当前权限一样,Yii 正在创建 Controller 的实例并仅查看这些访问规则。另外,就像您只查看特定操作的权限一样,Yii 也只查看与当前操作相关的规则。它可以像返回嵌套数组的值一样轻松地访问这些权限。
就用户而言,它也只查看当前用户;当前用户名、当前用户角色等。不同之处在于,Yii 在规则中允许有多个属性,而不是与用户关联的单个权限值。
您似乎不喜欢这种方法,因为您认为权限应该在一个地方处理。在某些情况下这可能更简单,但在其他情况下则更困难。当您有多个 Controller 并且每个 Controller 中有多个操作时会发生什么?您现在有一个非常大的数组需要管理,它引用来自多个不同上下文的数据。按照 Yii 的方式,当前 Controller 可以控制如何访问其数据结构。这符合 Yii 的 MVC 结构和封装的概念。
您的解决方案在某些方面更加优雅,但它取决于这样一种想法:权限只需要以级联单向结构来构建。我的意思是,您的权限就像一条长长的走廊,有门将一个区域与另一个区域分隔开。如果用户没有一扇门的 key ,他们应该无法访问下一扇门,等等。但是,在您的示例中,如果您需要用户既查看内容又无法更新内容,会发生什么情况创建新内容?这是一个更加复杂的场景,需要使用角色来处理。因此,您必须处理数组中的规则,就像 Yii 所做的那样。除了不是 Yii 的面向对象方法之外,您将所有内容都嵌入到一个长数组中。
所以也许你的解决方案在某些情况下会起作用,但我相信你可以明白为什么 Yii 选择它的方法,因为默认情况下它可以在更多情况下起作用。
关于php - Yii 的 accessRules 误解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14243210/