rbac权限管理
jianfly.com 2019-01-31 2071次浏览
四张表
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
命令 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'], ]], ]'
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 ?>
- 上一篇:全文检索ElasticSearch
- 下一篇:yii2用户认证机制