本文目的
接着上一篇文章yii2系列(一)项目搭建,以及常用组件的安装配置,继续配置yii2的各种组件
包括权限管理,菜单等。
环境要求
按照yii2系列(一)项目搭建,以及常用组件的安装配置配置完毕。
完整步骤
参考:
yii2搭建完美后台并实现rbac权限控制实例教程
yii2权限控制rbac之rule详细讲解
yii2-admin 插件使用简要教程
yii2 rbac权限控制之菜单menu详细教程
Yii2全面解析之权限管理RBAC
yii2搭建完美后台并实现rbac权限控制实例教程
Yii2实用基础学习笔记(十):RBAC
RBAC简介
RBAC
,即基于角色的访问控制(Role-Based Access Control)。
RBAC
支持三个著名的安全原则:最小权限原则,责任分离原则和数据抽象原则。
Yii2的RBAC核心文件在@vendor\yiisoft\yii2\rbac目录下,数据表的创建信息在该目录的 migrations` 目录下。
许可(Permission):包括许可标识、许可名称、受控对象、操作标识等。给出了受控对象与操作算子的对应关系。
角色(Role):包括角色标识、角色名称、角色基数、角色可用标识等。是系统角色集,由系统管理员定义角色。
用户(User):包括用户标识、用户姓名、用户登录密码等。是系统中的个体用户集,随用户的添加与删除动态变化。
规则(Rule):与一个角色或者权限关联。一个规则用一段代码代表, 规则的执行是在检查一个用户是否满足这个角色或者权限时进行的。
举个例子,下面是角色和用户的模拟设置:
//用户
[
管理员admin =>[
管理员角色
用户角色
其他角色
]
普通用户 =>[
用户角色
其他角色
]
]
//角色
[
管理员角色=>[
查看用户相关许可=>[
'/admin/user/index',
'/admin/user/view'
]
分配权限相关许可=>[
'/admin/assignment/index',
'/admin/assignment/vieww'
]
]
用户角色=>[
登陆登出相关许可=>[
'/user/login',
'/site/logout'
]
]
其他角色=>[
...
]
游客角色=>[
游客默认路由=>'/user/login'
]
]
前期准备
显示admin管理菜单
第一种方法:
首先,我们把下面这一段代码放到\frontend\themes\adminlte\layouts\left.php
中的<section class="sidebar">
标签中,放在哪无所谓。添加这个是为了方便临时访问。
<ul class="sidebar-menu">
<li class="">
<a href="#">
<i class="fa fa-circle-o"></i>
<span>权限管理</span>
<span class="pull-right-container"><i class="fa fa-angle-left pull-right"></i></span>
</a>
<ul class="treeview-menu" style="display: none;">
<li><a href="/admin/assignment/index"><i class="fa fa-circle-o"></i> <span>分配</span></a></li>
<li class=""><a href="/admin/permission/index"><i class="fa fa-circle-o"></i> <span>权限列表 </span></a></li>
<li><a href="/admin/user/index"><i class="fa fa-circle-o"></i> <span>用户列表</span></a></li>
<li><a href="/admin/menu/index"><i class="fa fa-circle-o"></i> <span>菜单列表</span></a></li>
<li><a href="/admin/rule/index"><i class="fa fa-circle-o"></i> <span>规则列表</span></a></li>
<li><a href="/admin/role/index"><i class="fa fa-circle-o"></i> <span>角色列表</span></a></li>
<li><a href="/admin/route/index"><i class="fa fa-circle-o"></i> <span>路由列表</span></a></li>
</ul>
</li>
</ul>
添加完上面的代码刷新页面左侧会出现类似下面图片的菜单,可以方便的访问admin的管理功能。
第二种方法:
其实还有另一种添加菜单的方法,但是那种方法需要用admin自带的layout。
打开\frontend\config\main.php
文件,在对应位置改成下面的代码
//额外安装的模块
'modules' => [
//加载user
'user' => [
'class' => 'dektrium\user\Module',
],
//加载admin
'admin' => [
'class' => 'mdm\admin\Module',
'layout' => 'left-menu',//yii2-admin的导航菜单
],
],
添加了'layout' => 'left-menu'
之后就可以看到admin自带的菜单了。
点击帮助显示默认页面,点击应用回到网站layout。
创建测试文件
使用gii创建一个controller和view文件夹,用来测试我们的权限,我这里起的名字是RbactestController
。
我们在\frontend\controllers\RbactestController.php
中添加四个方法,用来测试。
<?php
namespace frontend\controllers;
class RbactestController extends \yii\web\Controller
{
public function actionIndex()
{
return $this->render('index');
}
public function actionAdd()
{
return $this->render('index');
}
public function actionDelete()
{
return $this->render('index');
}
public function actionUpdate()
{
return $this->render('index');
}
public function actionSelect()
{
return $this->render('index');
}
}
在\frontend\views\rbactest\index.php
中添加一个echo用来表示当前执行的方法。
<?php
/* @var $this yii\web\View */
//输出当前路由
echo '<h1>'.$this->context->module->requestedRoute.'</h1>';
?>
我添加完之后尝试访问/rbactest
,发现返回提示您没有执行此操作的权限。
,现在我们尝试添加菜单和许可来控制权限。
创建菜单,设置权限
添加路由
在左边菜单找到路由列表,将需要分配的路由,添加到右边。
我添加的路由为,在中间可以看到我添加的5个rbactest的路由
/admin/assignment/assign
/admin/assignment/index
/admin/assignment/revoke
/admin/assignment/view
/admin/default/index
/admin/menu/create
/admin/menu/delete
/admin/menu/index
/admin/menu/update
/admin/menu/view
/admin/permission/assign
/admin/permission/create
/admin/permission/delete
/admin/permission/index
/admin/permission/remove
/admin/permission/update
/admin/permission/view
/admin/role/assign
/admin/role/create
/admin/role/delete
/admin/role/index
/admin/role/remove
/admin/role/update
/admin/role/view
/admin/route/assign
/admin/route/create
/admin/route/index
/admin/route/refresh
/admin/route/remove
/admin/rule/create
/admin/rule/delete
/admin/rule/index
/admin/rule/update
/admin/rule/view
/admin/user/activate
/admin/user/change-password
/admin/user/delete
/admin/user/index
/admin/user/login
/admin/user/logout
/admin/user/request-password-reset
/admin/user/reset-password
/admin/user/signup
/admin/user/view
/debug/default/db-explain
/debug/default/download-mail
/debug/default/index
/debug/default/toolbar
/debug/default/view
/gii/default/action
/gii/default/diff
/gii/default/index
/gii/default/preview
/gii/default/view
/rbactest/add
/rbactest/delete
/rbactest/index
/rbactest/select
/rbactest/update
/site/captcha
/site/logout
/user/admin/assignments
/user/admin/block
/user/admin/confirm
/user/admin/create
/user/admin/delete
/user/admin/index
/user/admin/info
/user/admin/resend-password
/user/admin/switch
/user/admin/update
/user/admin/update-profile
/user/profile/index
/user/profile/show
/user/recovery/*
/user/recovery/request
/user/recovery/reset
/user/registration/confirm
/user/registration/connect
/user/registration/register
/user/registration/resend
/user/security/auth
/user/security/login
/user/security/logout
/user/settings/account
/user/settings/confirm
/user/settings/delete
/user/settings/disconnect
/user/settings/networks
/user/settings/profile
添加权限
权限管理->权限列表->新增权限
按照下面的列表添加权限,每个路由都附带上index路由(其实index没什么用,因为是没办法在菜单中直接进入index的)
rbac add=>[
/rbactest/index
/rbactest/add
]
rbac delete=>[
/rbactest/index
/rbactest/delete
]
rbac update=>[
/rbactest/index
/rbactest/update
]
rbac select=>[
/rbactest/index
/rbactest/select
]
添加菜单
权限管理->菜单列表->新增菜单
首先添加一个叫做rbac_test
的顶级菜单,也就是不写父级名称和路由的,剩下四个菜单按照类似下面的格式写到刚才添加的顶级menu里。
添加角色
设置了权限还不够,需要在权限和用户中间加上一层角色。
因为有一些权限是共享的,为了不重复给某一个用户添加权限,需要添加角色。
用户角色里面只添加了一个叫做用户基础
的权限,里面包括了基本的权限,登出、主页等。
系统管理员角色里面添加了两个权限,权限管理
和用户基础
,把admin路由加到了权限管理
里面。
给账号添加权限
可以看到我已经给moozik账号分配了用户
和系统管理员
两个角色,又添加了两个权限分别是add和del。
也就是说虽然yii的rbac支持使用用户->角色->权限->路由
的方法添加权限到账户,但是可以跳过其中的角色直接给账户
分配权限
。
添加完成之后将下面代码添加到\frontend\themes\adminlte\layouts\left.php
,并将同名方法注释掉,如果你在菜单也添加了admin权限管理的路由,那就可以把上面我们临时添加的菜单删掉了。
<?=dmstr\widgets\Menu::widget( [
'options' => ['class' => 'sidebar-menu'],
'items' => MenuHelper::getAssignedMenu(Yii::$app->user->id),
] );?>
添加完成,刷新页面,左侧菜单已经有了刚才添加的两个权限对应的菜单。
rbac add
权限对应add
菜单rbac del
权限对应delete
菜单
我起名字的能力比较差,希望你没有被绕晕。
我的理解是这样,权限和路由是一对多的关系,目录跟路由是一对一的关系。
猜测生成左侧目录的过程:
- 获取用户moozik的角色和权限
- 获取用户moozik可访问的所有路由
- 获取用户moozik可访问路由对应的所有目录
进阶用法
权限判断
打开\frontend\views\rbactest\index.php
,在其中加入下面的代码。
<h4>你的权限:</h4>
<ul>
<?php
//权限列表
$permission=['rbac add','rbac del','rbac update','rbac select'];
foreach($permission as $item){
//检查当前用户是否有权限
if(Yii::$app->user->can($item)){
echo '<li>'.$item.'</li>';
}
}
?>
</ul>
访问/rbactest
,可以看到使用Yii::$app->user->can(permission)
可以判断当前用户的权限。
某些场景下,我们需要在一个功能中区分权限,比如一个按钮或者一段数据是否显示,这个时候就可以使用这个方法进行判断。
当然不只是判断权限,也可以增删改查权限信息,这样就可以实现更加复杂的权限控制。然而yii给我们准备了更细的权限控制。
规则文件
关于规则控制网上的资料不太多,可以参考yii2权限控制rbac之rule详细讲解
在我们添加权限的时候,页面中有一个规则名称
,这个是可为空的选项,也就是说是更进一步的控制。
举个例子:
5个管理员管理一个网站,我们希望他们的文章互不干扰,A的文章自己写完了别人不能改不能删,只能自己改自己删。
这个时候上面写的那个权限判断就没用了,因为这几个人都有修改文章那个路由的访问权限,而需要用文章创建人去判断。
开始我们的实验。
为了方便测试,我在数据库中复制了我的moozik账号,粘贴成moozik2方便测试两个账号。
我们准备让moozik只能操作单数id,moozik2只能操作复数id,如果没有id也可以访问。
添加下面的代码到\frontend\views\rbactest\index.php
,用来显示当前的id。
<h2>参数:<?=Yii::$app->request->get('id')?></h2>
保存下面的代码到\frontend\components\RbactestRule.php
<?php
namespace frontend\components;
use Yii;
use yii\rbac\Rule;
class RbactestRule extends Rule
{
public $name = 'rbactest';
public function execute($user, $item, $params)
{
// 这里先设置为false,逻辑上后面再完善
return false;
}
}
按照图片中的样子将规则文件添加到任意一个权限中。
刷新页面,发现add目录是有的,但是尝试打开add页面发现返回没有权限,这就说明添加的规则文件生效了,规则文件中是无脑返回false的,所以不可能通过权限检测。现在我们完善规则文件。
<?php
namespace frontend\components;
use Yii;
use yii\rbac\Rule;
class RbactestRule extends Rule
{
public $name = 'rbactest';
public function execute($user, $item, $params)
{
$id = Yii::$app->request->get('id');
$username = Yii::$app->user->identity->username;
if(empty($id)){
return true;
}
if($id % 2 === 0 and $username === 'moozik2'){
return true;
}else if($id % 2 !== 0 and $username === 'moozik'){
return true;
}
return false;
}
}
经过尝试,moozik账号只能访问单数id。
我给moozik2添加了rbactest里面所有的权限,并且也是只能访问指定的复数id。
当然在真实情况中肯定是去数据库查询,或者其他一些操作。execute()
方法传进来的$user
是用户id,可以方便的进行权限检查。