我正在尝试使用 Yii 构建一个站点,发现自己处于需要对 Yii 中的访问控制隐喻进行一些澄清的情况。具体来说,可以覆盖的后代中的accessRules方法CController
。
先决条件:
这是 Gii 默认生成的代码,与文档非常相似:
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
、特定action
和特定user
是已知的。例如,如果用户是来宾,我看不出有任何理由为“管理员”角色或经过身份验证的用户定义规则。
推理:
经过一番阐述,我想出了以下实现:
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
使用当前用户“权限”(照常从数据库读取)、当前控制器和操作来计算单个布尔值true
或false
值作为访问决策。
这种方法有什么问题?为什么 Yii 默认不使用这样简单的东西?
The Gii-generated accessRules
above do not only look excessive, but also imply that access rules are scattered among many controllers. In my approach a single and compact ACL is used.