1. RBAC 权限管理基本概念;
-
相关概念:
-
Role
Based
Access
Control:基于
角色的访问控制
-
RBAC 提供了一个简单而强大的集中式访问控制机制
-
关键字:
-
用户:Web 应用中的认证基数
-
角色 Role(角色是权限的集合):整合权限的集合,可以包含用户、也可以包含权限
-
权限 Permission(操作):控制器当中的相关方法
-
RBAC 权限认证流程:
-
用户登录后认证用户的角色
-
根据角色查询出角色该有的权限(操作)列表
-
当用户访问某一个权限(操作)是判断该用户是否拥有该操作的访问的能力
-
Yii2 的 RBAC 实现方式 1:数据库
-
储存角色或权限的表 auth_item
-
角色对应权限相关表 auth_item_child:角色拥有哪些权限
-
角色和权限同时存储在第一张表
-
用户角色(权限)表 auth_assignment:可以为用户分配角色,也可以为用户分配对应的权限
-
规则表 auth_role:提供额外权限的认证规则
INSERT INTO `auth_item` SET name = 'admin', type = 1, description = '管理员';
INSERT INTO `auth_item` SET name = 'category/*', type = 2, description = 'category/*';
INSERT INTO `auth_item` SET name = 'category/add', type = 2, description = 'category/add';
INSERT INTO `auth_item` SET name = 'category/del', type = 2, description = 'category/del';
INSERT INTO `auth_item_child` SET parent = 'admin', child = 'category/*';
INSERT INTO `auth_item_child` SET parent = 'admin', child = 'category/add';
INSERT INTO `auth_assignment` SET item_name = 'admin', user_id = 1;
INSERT INTO `auth_assignment` SET item_name = 'guest', user_id = 2;
-
数据表分析:
-
管理表:yii\rbac\DbManager
-
数据表不需要手动创建:yii migrate --migrationPath=@yii/rbac/migrations
-
Yii2 的 RBAC 实现方式 2:文件
-
@app/rbac 将权限数据全部都保存在应用目录下的 rbac 目录中
-
文件分析:
-
管理文件:yii\rbac\PhpManager
-
存储路径:@app/rbac
-
所有的数据文件不需要手动创建
-
使用基本类:
-
yii\rbac\Item:管理角色或者权限的基类,用字段 type 来区分
-
yii\rbac\Role:Role 为代表角色的类(Item 子类)
-
yii\rbac\Permission:控制权限操作的类(Item 子类)
-
yii\rbac\Assignment:给用户分配角色(权限),用户与角色的关联
-
yii\rbac\Rule:判断角色权限的额外规则
2. 配置 RBAC;
cd /data/project/test/yii22/basic
./yii hello/index
- 修改配置文件
basic/config/console.php
'authManager' => [
'class' => 'yii\rbac\DbManager',
'itemTable' => 'auth_item',
'itemChildTable' => 'auth_item_child',
'assignmentTable' => 'auth_assignment',
],
./yii migrate --migrationPath=@yii/rbac/migrations
yes
- 新建 basic/commands/RbacController.php
<?php
namespace app\commands;
use Yii;
use yii\console\Controller;
class RbacController extends Controller{
public function actionInit(){
$trans = Yii::$app->db->beginTransaction();
try{
$dir = dirname(dirname(__FILE__)) . '/controllers';
$controllers = glob($dir . '/*');
$permissions = [];
foreach ($controllers as $controller){
$content = file_get_contents($controller);
preg_match('/class ([a-zA-Z]+)Controller/', $content, $match);
$cName = $match[1];
$permissions[] = strtolower($cName . '/*');
preg_match_all('/public function action([a-zA-Z_]+)/', $content, $matches);
foreach ($matches[1] as $aName){
$permissions[] = strtolower($cName .'/'. $aName);
}
}
$auth = Yii::$app->authManager;
foreach($permissions as $permission){
if(!$auth->getPermission($permission)){
$obj = $auth->createPermission($permission);
$obj->description = $permission;
$auth->add($obj);
}
}
$trans->commit();
echo 'import success';
} catch (\Exception $e){
$trans->rollback();
echo 'import fail';
print_R($e->getMessage());
}
}
}
./yii rbac/init
3. 后台创建用户角色;
-
场景:
-
在后台权限列表里,点击“分配权限”,就应该给某一个角色去分配对应的权限的节点
-
在 Yii2 的 RBAC 中,提供了另外一种模式,不仅可以给角色添加
权限节点,还可以给角色添加
角色节点。假设普通用户拥有某些权限列表,当 manager 将 user 归纳为他下面的一个子角色的时候,manager 就拥有了 user 的所有权限。所以说在为一个角色分配权限的时候,可以分配两种内容:一种是可以给角色分配子角色,另外一种是可以给角色分配子节点
-
需要用到的表:shop_auth_item_child
- 修改
basic/modules/controllers/RbacController.php
<?php
namespace app\modules\controllers
use Yii;
use yii\data\ActiveDataProvider;
use yii\db\Query;
use\app\modules\models\Rbac;
class RbacController extends CommonController{
public $mustlogin = ['createrole', 'roles', 'assignitem'];
public function actionAssignitem($name){
$name = htmlspecialchars($name);
$auth = Yii::$app->authManager;
$parent = $auth->getRole($name);
if (Yii::$app->request->isPost) {
$post = Yii::$app->request->post();
if (Rbac::addChild($post['children'], $name)) {
Yii::$app->session->setFlash('info', '分配成功');
}
}
$roles = Rbac::getOptions($auth->getRoles(), $parent);
$permissions = Rbac::getOptions($auth->getPermissions(), $parent);
return $this->render('_assignitem', [
'parent' => $name,
'roles' => $roles,
'permissions' => $permissions,
]);
}
}
- 修改
basic/modules/models/Rbac.php
<?php
namespace app\modules\models;
use yii\db\ActiveRecord;
use Yii;
class Rbac extends ActiveRecord {
public static function getOptions($data, $parent){
$return = [];
foreach ($data as $obj) {
if(!empty($parent) &&
$parent->name != $obj->name &&
Yii::$app->authManager->canAddChild($parent, $obj)){
$return[$obj->name] = $obj->description;
}
}
return $return;
}
public static function addChild($children, $name){
$auth = Yii::$app->authManager;
$itemObj = $auth->getRole($name);
if (empty($itemObj)) {
return false;
}
$trans = Yii::$app->db->beginTransaction();
try {
$auth->removeChildren($itemObj);
foreach ($children as $item) {
$obj = empty($auth->getRole($item)) ? $auth->getPermission($item) : $auth->getRole($item);
$auth->addChild($itemObj, $obj);
}
$trans->commit();
} catch(\Exception $e) {
$trans->rollback();
return false;
}
return true;
}
}