rbac权限管理

jianfly.com 2019-01-31 529次浏览

四张表

auth_item (role permission) 存储角色或权限

auth_item_child (role->permission) 角色对应权限

auth_assignment (user->role) 为用户分配角色或权限

auth_rule (rule) 提供额外的权限认证的规则

/config/web.php中配置

'authManager' => [
'class' => 'yii\rbac\DbManager', //class类
'itemTable' => '{{%auth_item}}', //指定四张表名
'itemChildTable' => '{{%auth_item_child}}',
'assignmentTable' => '{{%auth_asignment}}',
'ruleTable' => '{{%auth_rule}}',
‘defaultRoles’ => ['default'], //默认拥有角色default对应的权限
],

创建表

在console.php中增加authManager的配置

yii migrate –migrationPath=@yii/rbac/migrations 创建表

基本类

yii\rbac\Item — 角色或者权限的基类,用字段type来区分

yii\rbac\Role — Role为代表角色的类

yii\rbac\Permission — 控制权限操作的类

yii\rbac\Assignment — 用户与角色的关联

yii\rbac\Rule — 判断角色权限的额外规则

创建角色

public function actionCreaterole() 
{
if(Yii::$app->request->isPost) {
$auth = Yii::$app->authManager;  //DbManager对象
$role= $auth->createRole( null );  //创建role对象,管理item表的
$post = Yii::$app->request->post();
if (empty($post['name']) || empty($post['description']) ) {
throw new \Exception('参数错误');
}
$role->name = $post['name'];
$role->description = $post['description'];
$role->ruleName = empty($post['rule_name']) ? null : $post['rule_name'];
$role->data = empty($post['data']) ? null : $post['data'];
i($auth->add($role)) {
Yii::$app->session->setFlash( 'info', '添加成功' );
}
}
return $this>render('_createitem'); //加载表单
}

前台模板表单使用Html类创建,因为没有model类去创建表单

角色列表(GridView显示表格)

use \yii\data\ActiveDataProvider;
use \yii\db\Query;
public function actionRoles() 
{
$auth = Yii::$app->authManager;
$data = new ActiveDataProvider([
'query' => (new Query)->from($auth->itemTable)->where('type = 1')->orderBy('created_at desc'),
'pagination' => ['pageSize' => 5],
]);
return $this->render('_items', ['dataProvider' => $data]);
}
<?php
use yii\grid\GridView;
use tii\helpers\Html;
?>
<?php
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [ //列
[
'class' => 'yii\grid\SerialColumn',
],
'description:text:名称',
'name:text:标识',
'rule_name:text:规则名称',
'created_at:datetime:创建时间',
'updated_at:datetime:更新时间',
[
'class' => 'yii\grid\ActionColumn',
'header' => '操作',
'template' => '{assign} {update} {delete}',
'buttons' => [
'assign' => function ( $url, $model, $key ) {
return Html::a( '分配权限', ['assignitem', 'name' => $model['name']] ); //链接到r=admin/rbac/assignment?name=manager
},
'update' => function ( $url, $model, $key ) {
return Html::a( '更新', ['updateitem', 'name' => $model['name']] );
},
'delete' => function ( $url, $model, $key ) {
return Html::a( '删除', ['deleteitem', 'name' => $model['name']] );
},
],
],
],
'layout' => "\n{items}\n{summary}<div class='pagination pull-right'>{pager}</div>",
]);
?>

一键添加权限节点(只需要执行一次)

在commands里面建立RbacController.php

RbacController

命令 yii Rbac/init

role= $auth->createRole( null );  //创建role对象,管理item表的
$auth->getPermission( $permission ); //判断权限是否已经存在 (permission的type为2,role的type为1)
$obj = $auth->createPermission($permission); //创建权限
$obj->description = $permission; //赋值
$auth->add($obj); //保存
$roles = $auth->getRoles(); //获取所有role对象
$permissions = $auth->getPermissions(); //获取所有权限对象
Yii::$app->authManager->canAddChild($parent, $obj); //parent能添加obj子节点
$auth->removeChildren($itemObj); //去除$itemObj的所有子节点
$auth->addChild($itemObj, $obj); //为itemObj添加obj子节点
$auth->getChildren($name); //获取名称为$name的对象的所有子节点
$auth->revokeAll($adminid); //去掉所有授权
Html::checkboxList( 'children', $children['roles'], $roles ); // name字段, 默认选中, value列表
Yii::$app->controller   //获取当前controller名称
public function beforeAction($action) { //验证权限
if(!parent::beforeAction($action)) {
return false;
}
$controller = $action->controller->id; //Controller名称
$actionName = $action->id;  //action名称
if(Yii::$app->admin->can($controller . '/*')) {
return true;
}
if(Yii::$app->admin->can($controller . '/' . $actionName)){
return true;
}
throw new \yii\web\UnauthorizedHttpException('对不起,您没有访问' . $controller . '/' . $actionName . '的权限');
}

自动添加adminid字段

use yii\behaviors\BlameableBehavior;
public function behaviors()
{
return [
[
'class' => BlameableBehavior::className(),
'createdByAttribute' => 'adminid', //创建
'updatedByAttribute' => null, //更新
'value' => Yii::$app->admin->id; //值
],
];
}

额外的rule验证

/models/AuthorRule.php中验证只能删除自己添加的分类

yse yii\rbac\Rule;
use Yii;
class AuthorRule extends Rule
{
public $name = "isAuthor";
public function execute( $user, $item, $params )
{
$action = Yii::$app->controller->action->id;
if($action == 'delete') {
$cateid = Yii::$app->request->get("id"); //或许需要删除的行的id
$cate = Category::findOne($cateid); //查找出这条分类的对象
return $cate->adminid == $user; //返回是否相等
}
return true;
}
}

auth表的处理

public function actionCreaterule()
{
if(Yii::$app->request->isPost) {
$post = Yii::$app->request->post();
if(empty($post['class_name'])) {
throw new \Exception('参数错误');
}
$className = "app\\models\\" . $post['class_name'];
if(class_exists($className)) {
throw new \Exception('规则类不存在');
}
$rule = new $className; //实例化
if(Yii::$app->authManager->add($rule)) {
Yii::$app->session->setFlash('info', '添加成功');
}
}
return $this->render('_createrule');
}

侧边栏的处理 /config/adminmenu.php

return [
['label' => '后台首页', ‘url’ => 'default/index', 'module' => 'default', 'icon' => 'icon-home', 'submenu' => []],
['label' => '管理员管理', 'url' => '#', 'module' => 'manage', 'icon' => 'icon-user', 'submenu' => [
['label' => '管理员列表', 'url' => 'managers'],
['label' => '添加管理员', 'url' => 'reg'],
]],
]'

adminmenu

web.php里配置

$adminmenu = require(__DIR__. '/adminmenu.php');
'params' => array_merge($params, ['adminmenu' => $adminmenu]),

页面中显示

<?php
$controller = Yii::$app->controller->id; //Controller名字
$action = Yii::$app->controller->action->id; //Action名字
foreach (Yii::$app->params['adminmenu'] as $menu) {
$show = "hidden;" //默认都是隐藏
if( Yii::$app->admin->can($menu['module']. '/*/') ) { //可以访问****/*
$show = "show"; //展示
} else {
if(empty ($menu['submenu']) && !Yii::$app->admin->can($menu['url']) ) {
continue; //没有子菜单并且可以访问一级菜单路径,跳出这次循环
} else {
foreach( $menu['submenu'] as $sub ) { //循环子菜单
if(Yii::$app->admin->can($menu['module'] . '/' . $sub['url'] )) { //可访问的子菜单
$show = "show";
}
}
}
}
//这里不结束}
?>
<li class="<?php echo $controller == $menu['module'] ? 'active' : ''; echo $show; ?>" >  <!--如果controller名字相同,就active-->
<a <?php echo !empty($menu['submenu']) ? ' class = "dropdown-toggle" ' : ''; ?> <!--判断是否有下拉-->
href="<?php echo $menu['url'] == '#' ? '#' : yii\helpers\Url::to([$menu['url']]); ?>" <!--链接为#或者生成路径-->
>
<i class="<?php echo $menu['icon']; ?>"></i>  <!--小图标-->
<span><?php echo $menu['label']; ?></span>  <!--菜单名-->
<?php if(!empty($menu['submenu'])) : ?>  <!--是否有子菜单-->
<i class="icon-chevron-down"></i>
<?php endif; ?>
</a>
<ul class="submenu <?php echo $controller == $menu['module'] && !empty($menu['submenu']) ? 'active' : '' ?>">
<?php foreach($menu['submenu'] as $sub): ?> <!--循环遍历子菜单-->
<?php if(!Yii::$app->admin->can($menu['module']. '/*' ) && !Yii::$app->admin->can($menu['module']. '/' . $sub['url']) )  continue; ?>  <!--如果不能访问就跳出这一次循环-->
<li><a href="<?php echo yii\helpers\Url::to([$menu['module']. '/' .$sub['url']]) ?>"> <?php echo $sub['label']; ?> </a></li>  <!--生成路径和名字-->
<?php endforeach; ?>
</ul>
</li>
<?php
} //结束foreach
?>