Yii框架的权限控制可以通过内置的RBAC(基于角色的访问控制)组件实现,该组件支持角色、权限、规则等核心概念,能够灵活适配多层级权限管理需求,适合大多数业务场景的权限管控要求。

Yii框架RBAC核心概念
在配置RBAC权限之前,需要先了解几个核心概念,这些概念是RBAC权限体系的基础:
- 角色:对应系统中的用户身份,比如管理员、普通用户、编辑等,一个用户可以关联多个角色。
- 权限:对应具体的操作权限,比如文章创建、文章删除、用户管理等,权限可以分配给角色。
- 规则:可选配置,用于实现更复杂的权限校验逻辑,比如校验文章作者只能删除自己发布的文章。
RBAC组件基础配置
首先需要在Yii框架的配置文件中启用RBAC组件,这里以Yii2高级模板为例,在common/config/main.php中添加如下配置:
return [
// 其他配置项
'components' => [
'authManager' => [
'class' => 'yiirbacDbManager',
// 存储RBAC数据的表前缀,可选配置
'itemTable' => '{{%auth_item}}',
'itemChildTable' => '{{%auth_item_child}}',
'assignmentTable' => '{{%auth_assignment}}',
'ruleTable' => '{{%auth_rule}}',
],
],
];
配置完成后,需要运行Yii的迁移命令生成RBAC相关的数据表,执行如下命令:
yii migrate --migrationPath=@yii/rbac/migrations
命令执行后会在数据库中生成四张表,分别存储权限项、权限继承关系、角色分配关系、规则数据。
角色与权限的创建
可以通过代码或者命令行的方式创建角色和权限,以下是使用代码创建角色和权限的示例:
// 获取authManager实例
$auth = Yii::$app->authManager;
// 创建删除文章的权限
$deletePostPermission = $auth->createPermission('deletePost');
$deletePostPermission->description = '删除文章权限';
$auth->add($deletePostPermission);
// 创建编辑角色
$editorRole = $auth->createRole('editor');
$editorRole->description = '编辑角色';
$auth->add($editorRole);
// 将删除文章权限分配给编辑角色
$auth->addChild($editorRole, $deletePostPermission);
// 创建管理员角色
$adminRole = $auth->createRole('admin');
$adminRole->description = '管理员角色';
$auth->add($adminRole);
// 管理员角色继承编辑角色的所有权限
$auth->addChild($adminRole, $editorRole);
用户与角色关联
创建好角色之后,需要将角色分配给对应的用户,示例代码如下:
// 获取authManager实例
$auth = Yii::$app->authManager;
// 将editor角色分配给用户ID为1的用户
$editorRole = $auth->getRole('editor');
$auth->assign($editorRole, 1);
// 将admin角色分配给用户ID为2的用户
$adminRole = $auth->getRole('admin');
$auth->assign($adminRole, 2);
权限校验实现
在需要校验权限的地方,可以通过authManager的checkAccess方法进行校验,也可以在控制器中使用行为统一校验权限:
方法一:直接调用校验方法
// 校验用户ID为1的用户是否有deletePost权限
$userId = 1;
$hasPermission = Yii::$app->authManager->checkAccess($userId, 'deletePost');
if ($hasPermission) {
echo '用户有删除文章权限';
} else {
echo '用户无删除文章权限';
}
方法二:控制器行为校验
在控制器中配置access行为,可以统一对控制器的操作进行权限校验:
namespace backendcontrollers;
use yiiwebController;
use yiifiltersAccessControl;
class PostController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'rules' => [
[
'allow' => true,
// 允许的操作
'actions' => ['delete'],
// 允许的角色,?代表游客,@代表登录用户
'roles' => ['editor'],
],
],
],
];
}
public function actionDelete($id)
{
// 删除文章的逻辑
// 只有拥有editor角色的用户才能访问这个操作
return $this->redirect(['index']);
}
}
自定义规则配置
如果需要实现更复杂的权限逻辑,比如仅允许文章作者删除自己的文章,可以自定义规则:
namespace backendrules;
use yiirbacRule;
class DeleteOwnPostRule extends Rule
{
public $name = 'deleteOwnPost';
/**
* @param string|int $user 用户ID
* @param yiirbacItem $item 权限项
* @param array $params 额外参数,这里传入文章的user_id
* @return bool 是否有权限
*/
public function execute($user, $item, $params)
{
return isset($params['post_user_id']) && $params['post_user_id'] == $user;
}
}
创建好规则之后,需要将规则关联到对应的权限:
$auth = Yii::$app->authManager;
// 创建规则实例
$rule = new backendrulesDeleteOwnPostRule();
$auth->add($rule);
// 创建带规则的权限
$deleteOwnPostPermission = $auth->createPermission('deleteOwnPost');
$deleteOwnPostPermission->description = '删除自己的文章';
$deleteOwnPostPermission->ruleName = $rule->name;
$auth->add($deleteOwnPostPermission);
// 将原deletePost权限作为父权限
$deletePostPermission = $auth->getPermission('deletePost');
$auth->addChild($deleteOwnPostPermission, $deletePostPermission);
// 将带规则的权限分配给editor角色
$editorRole = $auth->getRole('editor');
$auth->addChild($editorRole, $deleteOwnPostPermission);
校验带规则的权限时,需要传入额外的参数:
// 假设当前文章的作者是1,当前用户是2
$postUserId = 1;
$currentUserId = 2;
$hasPermission = Yii::$app->authManager->checkAccess($currentUserId, 'deleteOwnPost', ['post_user_id' => $postUserId]);
if ($hasPermission) {
echo '用户可以删除该文章';
} else {
echo '用户只能删除自己发布的文章';
}