1.RBAC为角色分配权限之展示表单
往数据库中添加记录
程序代码如下:
insert into sw_auth values(13,'系统管理',0,'','',13,0);
insert into sw_auth values(14,'角色管理',13,'Role','showlist','13-14',1);
新建shop/Admin/Controller/RoleController.class.php
程序代码如下:
//显示角色列表
public function showlist(){
$info = D() -> table('sw_role') ->select();
//$info = D('sw_role')->select();
//show_bug($info);
$this -> assign('info',$info);
$this -> display();
}
//进行权限分配
function distribute($role_id){
//echo $role_id;
$rinfo = D("Role") -> getByRole_id($role_id);
//查询全部的权限信息,放入模板显示并进行权限分配
$pauth_info = D('Auth') -> where('auth_level=0') -> select(); //父级权限
$sauth_info = D('Auth') -> where('auth_level=1') -> select(); //父级权限
$this -> assign('pauth_info',$pauth_info);
$this -> assign('sauth_info',$sauth_info);
$this -> assign('role_name',$rinfo['role_name']);
$this -> display();
}
新建shop/Admin/View/Role/showlist.html
程序代码如下:
<table class="table_a" border="1" width="100%">
<tbody>
<tr style="font-weight: bold;">
<td>序号</td>
<td>角色名称</td>
<td colspan="2" >操作</td>
</tr>
{foreach $info as $k => $v}
<tr id="product1">
<td >{$v@iteration}</td>
<td>{$v.role_name}</td>
<td><a href="{$smarty.const.__CONTROLLER__}/distribute/role_id/{$v.role_id}">分配权限</a>
</td>
</tr>
{/foreach}
</tbody>
</table>
新建shop/Admin/View/Role/distribute.html
程序代码如下:
<html>
<head>
<style type="text/css">
{literal}
li{list-style: none};
{/literal}
</style>
</head>
...
<body>
...
<form action="{$smarty.const.__SELF__}" method="post" enctype="multipart/form-data">
<div>
正在为角色:<span style="font-size: 25px;font-weight: bold;">{$role_name[]},</span>分配权限
</div>
{*首先显示父级权限,在内部嵌套判断显示对应的子集权限*}
<ul>
{foreach $pauth_info as $k => $v}
<li>{$v.auth_name}<input type="checkbox" name="authname[]"/>
<ul>
{foreach $sauth_info as $kk => $vv}
{if $vv.auth_pid == $v.auth_id}
<li>{$vv.auth_name}<input type="checkbox" name="authname"/></li>
{/if}
{/foreach}
</ul>
</li>
{/foreach}
</ul>
<input type="submit" value="分配权限"/>
</form>
...
</body>
</html>
2.RBAC为角色分配权限之收集表单信息
步骤:
1、制作表单显示具体被分配权限信息
2、收集权限信息在RoleModel模型里面保存
3、分配权限的时候,已经有的权限,复选框需要被选中
4、展示分配权限信息的表单对应控制器
shop/Admin/View/Role/distribute.html
程序代码如下:
<form action="{$smarty.const.__SELF__}" method="post" enctype="multipart/form-data">
<div>
正在为角色:<span style="font-size: 25px;font-weight: bold;">{$role_name},</span>分配权限
</div>
{*首先显示父级权限,在内部嵌套判断显示对应的子集权限*}
<ul>
{foreach $pauth_info as $k => $v}
<li>{$v.auth_name}<input type="checkbox" name="authname[]" value="{$v.auth_id}" />
<ul>
{foreach $sauth_info as $kk => $vv}
{if $vv.auth_pid == $v.auth_id}
<li>{$vv.auth_name}<input type="checkbox" name="authname[]" value="{$vv.auth_id}"/></li>
{/if}
{/foreach}
</ul>
</li>
{/foreach}
</ul>
<input type="submit" value="分配权限"/>
</form>
shop/Admin/Controller/RoleController.class.php
程序代码如下:
//进行权限分配
function distribute($role_id){
if (!empty($_POST)) {
//print_r($_POST);
//利用RoleModel模型中的一个专门方法实现权限分配
$role = new \Model\RoleModel();
//saveAuth接收到一维数组信息
$z = $role -> saveAuth($_POST['authname'],$role_id);
if ($z) {
echo "S";
} else {
echo "F";
}
} else {
//echo $role_id;
$rinfo = D("Role") -> getByRole_id($role_id);
//查询全部的权限信息,放入模板显示并进行权限分配
$pauth_info = D('Auth') -> where('auth_level=0') -> select(); //父级权限
$sauth_info = D('Auth') -> where('auth_level=1') -> select(); //父级权限
$this -> assign('pauth_info',$pauth_info);
$this -> assign('sauth_info',$sauth_info);
$this -> assign('role_name',$rinfo['role_name']);
$this -> display();
}
}
新建shop/Model/RoleModel.class.php
程序代码如下:
<?php
namespace Model;
use Think\Model;
class RoleModel extends Model{
//权限分配
//$auth是一维数组信息,给当前角色分配权限id信息
function saveAuth($auth,$role_id){
//把权限di信息由数组变为中间用逗号分隔的字符串信息
$auth_ids = implode(',', $auth);
show_bug($auth_ids);
//根据ids权限id信息查询具体操作方法信息
$info = D('Auth') -> select($auth_ids); //二维数组信息
//show_bug($info);
//拼装控制器和操作方法
$auth_ac ='';
foreach($info as $k => $v){
if (!empty($v['auth_c']) && !empty($v['auth_a'])) {
$auth_ac .= $v['auth_c']."-".$v['auth_a'].',';
}
}
$auth_ac = rtrim($auth_ac,',');//删除最右边的逗号
show_bug($auth_ac);
$sql="update sw_role set role_auth_ids='$auth_ids',role_auth_ac='$auth_ac' where role_id='$role_id'";
return $this->execute($sql);
}
}
遍历权限的时候把id与ids的数组作比较,判断是否是其中的一个元素,进而设置checked属性。
shop/Admin/View/Role/distribute.html
程序代码如下:
<form action="{$smarty.const.__SELF__}" method="post" enctype="multipart/form-data">
<div>
正在为角色:<span style="font-size: 25px;font-weight: bold;">{$role_name},</span>分配权限
</div>
{*首先显示父级权限,在内部嵌套判断显示对应的子集权限*}
<ul>
{foreach $pauth_info as $k => $v}
<li>{$v.auth_name}<input type="checkbox" name="authname[]" value="{$v.auth_id}"
{if in_array($v.auth_id,$auth_ids_arr) } checked='checked' {/if} />
<ul>
{foreach $sauth_info as $kk => $vv}
{if $vv.auth_pid == $v.auth_id}
<li>{$vv.auth_name}<input type="checkbox" name="authname[]" value="{$vv.auth_id}" {if in_array($vv.auth_id,$auth_ids_arr) } checked='checked' {/if}/></li>
{/if}
{/foreach}
</ul>
</li>
{/foreach}
</ul>
<input type="submit" value="分配权限"/>
</form>
shop/Admin/Controller/RoleController.class.php
程序代码如下:
//进行权限分配
function distribute($role_id){
if (!empty($_POST)) {
//print_r($_POST);
//利用RoleModel模型中的一个专门方法实现权限分配
$role = new \Model\RoleModel();
//saveAuth接收到一维数组信息
$z = $role -> saveAuth($_POST['authname'],$role_id);
if ($z) {
$this -> success('分配权限成功',U('showlist'));
} else {
$this -> error('分配权限失败',U('showlist'));
}
} else {
//echo $role_id;
$rinfo = D("Role") -> getByRole_id($role_id);
//查询全部的权限信息,放入模板显示并进行权限分配
$pauth_info = D('Auth') -> where('auth_level=0') -> select(); //父级权限
$sauth_info = D('Auth') -> where('auth_level=1') -> select(); //父级权限
//把当前角色对应的权限信息给查询出来
$authinfo = D('Role') -> getByRole_id($role_id);
//$auth_ids = $authinfo['role_auth_ids'];
//$auth_ids_arr = explode(',', $auth_ids);
$auth_ids_arr = explode(',', $authinfo['role_auth_ids']);
//show_bug($auth_ids_arr);
$this -> assign('pauth_info',$pauth_info);
$this -> assign('sauth_info',$sauth_info);
$this -> assign('auth_ids_arr',$auth_ids_arr);
$this -> assign('role_name',$rinfo['role_name']);
$this -> display();
}
}
3.RBAC展示权限列表信息
往数据库中添加记录
程序代码如下:
insert into sw_auth values(15,'权限管理',13,'Auth','showlist','13-15',1);
新建shop/Admin/Controller/AuthController.class.php
程序代码如下:
function showlist(){
$info = D('Auth') -> order('auth_path asc')->select();
//$info[X][auth_name] = '-->'auth_name
foreach ($info as $k => $v) {
$info[$k]['auth_name'] = str_repeat('-->', $v['auth_level']).$info[$k]['auth_name'];
}
$this -> assign('info',$info);
$this -> display();
}
新建shop/Admin/View/Auth/showlist.html
程序代码如下:
<table class="table_a" border="1" width="100%">
<tbody><tr style="font-weight: bold;">
<td>序号</td>
<td>权限名称</td>
<td>控制器</td>
<td>方法</td>
<td>全路径</td>
</tr>
{foreach $info as $k => $v}
<tr id="product1">
<td >{$v@iteration}</td>
<td><a href="#">{$v.auth_name}</a></td>
<td>{$v.auth_c}</td>
<td>{$v.auth_a}</td>
<td>{$v.auth_path}</td>
</tr>
{/foreach}
</tbody>
</table>
4.RBAC权限添加实现
权限添加实现
shop/Admin/Controller/AuthController.class.php
程序代码如下:
function showlist(){
$info = $this -> getinfo();
$this -> assign('info',$info);
$this -> display();
}
function getinfo(){
$info = D('Auth') -> order('auth_path asc')->select();
//$info[X][auth_name] = '-->'auth_name
foreach ($info as $k => $v) {
$info[$k]['auth_name'] = str_repeat('-->', $v['auth_level']).$info[$k]['auth_name'];
}
return $info;
}
function add(){
if (!empty($_POST)) {
//print_r($_POST);
//在AuthModel中通过一个指定方法实现权限添加
$auth = new \Model\AuthModel();
$z = $auth -> addAuth($_POST);
if ($z) {
echo "S";
} else {
echo "F";
}
} else {
//获得父级权限信息
$info = $this -> getinfo();
//show_bug(info);
//从$info中获得信息,例如:array(1=>'商品管理',2=>'添加商品',3=>'订单管理')
//以便在smarty中使用{html_optins}
$authinfo = array();
foreach ($info as $k => $v) {
$authinfo[$v['auth_id']] = $v['auth_name'];
}
$this -> assign('authinfo',$authinfo);
$this -> display();
}
}
shop/Admin/View/Auth/add.html
程序代码如下:
<form action="{$smarty.const.__SELF__}" method="post" enctype="multipart/form-data">
<table border="1" width="100%" class="table_a">
<tr>
<td>权限名称</td>
<td><input type="text" name="auth_name" /></td>
</tr>
<tr>
<td>权限父级</td>
<td>
<select name="auth_pid">
<option value="0">请选择</option>
{html_options options=$authinfo}
</select>
</td>
</tr>
<tr>
<td>权限控制器</td>
<td><input type="text" name="auth_c" /></td>
</tr>
<tr>
<td>权限操作方法</td>
<td><input type="text" name="auth_a" /></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="添加">
</td>
</tr>
</table>
</form>
shop/Admin/Controller/AuthController.class.php
程序代码如下:
//添加权限方法
function addAuth($auth){
//$auth中存在4个信息,还缺两个关键信息:auth_path和auth_level
//1、insert生成一个新纪录
//2、update把path和level更新进去
$new_id = $this -> add($auth); //返回新纪录的主键id值
//path的值分为两种情况
//全路径:父级全路径与本身id的连接信息
//1、当前权限是顶级权限,path=$new_id
//2、当前权限是非顶级权限,path=父级全路径+$new_id
if ($auth['auth_pid'] == 0) {
$auth_path = $new_id;
} else {
//查询指定父级的全路径,条件:$auth['auth_pid']
$pinfo = $this -> find($auth['auth_pid']); //查询出父级的记录信息
$p_path = $pinfo['auth_path'];//父级全路径
$auth_path = $p_path."-".$new_id;
}
//auth_level数目:全路径中短横线的个数
//把全路径变为数组,计算数组的个数和减去1,就是level的信息
$auth_level = count(explode('-', $auth_path))-1;
$sql="update sw_auth set auth_path='$auth_path',auth_level='$auth_level' where auth_id='$new_id'";
return $this->execute($sql);
}
优化之“添加权限时,不显示第三级别的权限”
有一些权限是不便于在左侧菜单栏中显示。
比如:商品管理下商品列表中每样商品的修改/删除,属于第三级别的权限。
而目前我们在系统管理下的权限管理中添加的权限是可以在选择到第二级别的权限,比如:
![第三级别的权限](https://i-blog.csdnimg.cn/blog_migrate/db33be2442d4c46f83ccd83fe0730c31.jpeg)
第三级别的权限
![权限管理](https://i-blog.csdnimg.cn/blog_migrate/d8b4d9507f20d252edda22773c69f962.jpeg)
权限管理
![数据库记录](https://i-blog.csdnimg.cn/blog_migrate/d04b464cae97d6871647ef1a135c68e3.jpeg)
数据库记录
![第三级别的权限本不应该出现](https://i-blog.csdnimg.cn/blog_migrate/0582a472994117ac24ee8a1e8e6b8944.jpeg)
第三级别的权限本不应该出现
出于合理性考虑,我们需要做如下优化
添加权限父级只显示level=0或level=1
shop/Admin/Controller/AuthController.class.php
程序代码如下:
function add(){
if (!empty($_POST)) {
//print_r($_POST);
//在AuthModel中通过一个指定方法实现权限添加
$auth = new \Model\AuthModel();
$z = $auth -> addAuth($_POST);
if ($z) {
echo "S";
} else {
echo "F";
}
} else {
//获得父级权限信息
$info = $this -> getinfo(true);
//show_bug(info);
//从$info中获得信息,例如:array(1=>'商品管理',2=>'添加商品',3=>'订单管理')
//以便在smarty中使用{html_optins}
$authinfo = array();
foreach ($info as $k => $v) {
$authinfo[$v['auth_id']] = $v['auth_name'];
}
$this -> assign('authinfo',$authinfo);
$this -> display();
}
}
function getinfo($flag=false){
//如果$flag标志为false,查询全部的权限信息
//如果$flag标志为true,查询level=0/1的权限信息
$auth = D('Auth');
if ($flag == true) {
$info = D('Auth') -> where('auth_level<2') -> order('auth_path asc')->select();
} else {
$info = D('Auth') ->order('auth_path asc')->select();
}
//$info[X][auth_name] = '-->'auth_name
foreach ($info as $k => $v) {
$info[$k]['auth_name'] = str_repeat('-->', $v['auth_level']).$info[$k]['auth_name'];
}
return $info;
}
![移除第三级别权限](https://i-blog.csdnimg.cn/blog_migrate/32ba0887fc825564749dfc8b1db7bf91.jpeg)
移除第三级别权限
优化之“为角色分配权限,显示第三级别的权限”
shop/Admin/Controller/RoleController.class.php
程序代码如下:
//进行权限分配
function distribute($role_id){
if (!empty($_POST)) {
//print_r($_POST);
//利用RoleModel模型中的一个专门方法实现权限分配
$role = new \Model\RoleModel();
//saveAuth接收到一维数组信息
$z = $role -> saveAuth($_POST['authname'],$role_id);
if ($z) {
$this -> success('分配权限成功',U('showlist'));
} else {
$this -> error('分配权限失败',U('showlist'));
}
} else {
//echo $role_id;
$rinfo = D("Role") -> getByRole_id($role_id);
//查询全部的权限信息,放入模板显示并进行权限分配
$pauth_info = D('Auth') -> where('auth_level=0') -> select(); //父级权限
$sauth_info = D('Auth') -> where('auth_level=1') -> select(); //父级权限
$tauth_info = D('Auth') -> where('auth_level=2') -> select(); //父级权限
//把当前角色对应的权限信息给查询出来
$authinfo = D('Role') -> getByRole_id($role_id);
//$auth_ids = $authinfo['role_auth_ids'];
//$auth_ids_arr = explode(',', $auth_ids);
$auth_ids_arr = explode(',', $authinfo['role_auth_ids']);
//show_bug($auth_ids_arr);
$this -> assign('pauth_info',$pauth_info);
$this -> assign('sauth_info',$sauth_info);
$this -> assign('tauth_info',$tauth_info);
$this -> assign('auth_ids_arr',$auth_ids_arr);
$this -> assign('role_name',$rinfo['role_name']);
$this -> display();
}
}
shop/Admin/View/Role/distribute.html
程序代码如下:
<form action="{$smarty.const.__SELF__}" method="post" enctype="multipart/form-data">
<div>
正在为角色:<span style="font-size: 25px;font-weight: bold;">{$role_name},</span>分配权限
</div>
{*首先显示父级权限,在内部嵌套判断显示对应的子集权限*}
<ul>
{foreach $pauth_info as $k => $v}
<li>{$v.auth_name}<input type="checkbox" name="authname[]" value="{$v.auth_id}"
{if in_array($v.auth_id,$auth_ids_arr) } checked='checked' {/if} />
<ul>
{foreach $sauth_info as $kk => $vv}
{if $vv.auth_pid == $v.auth_id}
<li>{$vv.auth_name}<input type="checkbox" name="authname[]" value="{$vv.auth_id}" {if in_array($vv.auth_id,$auth_ids_arr) } checked='checked' {/if} />
<ul>
{foreach $tauth_info as $kkk => $vvv}
{if $vvv.auth_pid == $vv.auth_id}
<li>{$vvv.auth_name}<input type="checkbox" name="authname[]" value="{$vvv.auth_id}" {if in_array($vvv.auth_id,$auth_ids_arr) } checked='checked' {/if} /></li>
{/if}
{/foreach}
</ul>
</li>
{/if}
{/foreach}
</ul>
</li>
{/foreach}
</ul>
<input type="submit" value="分配权限"/>
</form>
5.RBAC管理员设置角色
shop/Admin/Controller/ManagerController.class.php
程序代码如下:
function getRoleInfo(){
//查询全部角色的信息
$rrinfo = D('Role') -> select(); //二维数组信息
//array(1=>'经理',2=>'主管')
$rinfo = array();
foreach ($rrinfo as $k => $v) {
$rinfo[$v['role_id']] = $v['role_name']; //array(1=>'经理',2=>'主管')
}
return $rinfo;
}
function showlist(){
$info = D('Manager') -> select();
//查询全部角色的信息
$rinfo = $this -> getRoleInfo();
$this -> assign('rinfo',$rinfo);
$this -> assign('info',$info);
$this->display();
}
shop/Admin/View/Manager/showlist.html
程序代码如下:
<table class="table_a" border="1" width="100%">
<tbody><tr style="font-weight: bold;">
<td>序号</td>
<td>管理员名称</td>
<td>角色</td>
<td colspan="2" >操作</td>
</tr>
{foreach $info as $k => $v}
<tr id="product1">
<td >{$v@iteration}</td>
<td><a href="#">{$v.mg_name}</a></td>
<td>{$rinfo[$v.mg_role_id]}</td>
<td><a href="{$smarty.const.__CONTROLLER__}/upd/mg_id/{$v.mg_id}">修改</a></td>
</tr>
{/foreach}
</tbody>
</table>
shop/Admin/Controller/ManagerController.class.php
程序代码如下:
function upd($mg_id){
if (!empty($_POST)) {
//print_r($_POST);
$manager = D('Manager');
$manager -> create();
$z = $manager -> save();
if ($z) {
$this -> success('修改管理员成功',U('showlist'));
} else {
$this -> error('修改管理员失败',U('showlist'));
}
} else {
//获得被修改管理员的信息
$info = D('Manager') -> find($mg_id);
//查询全部角色的信息
$rinfo = $this -> getRoleInfo();
$this -> assign('info',$info);
$this -> assign('rinfo',$rinfo);
$this -> assign('mg_id',$mg_id);
$this -> assign('role_id',$info['mg_role_id']);
$this->display();
}
}
shop/Admin/View/Manager/upd.html
程序代码如下:
<form action="{$smarty.const.__SELF__}" method="post" enctype="multipart/form-data">
<input type="hidden" name="mg_id" value="{$mg_id}" />
<table border="1" width="100%" class="table_a">
<tr>
<td>管理员名称</td>
<td><input type="text" name="mg_name" value="{$info.mg_name}" /></td>
</tr>
<tr>
<td>管理员角色</td>
<td>
<select name="mg_role_id">
<option value="0">请选择</option>
{html_options options=$rinfo selected=$role_id}
</select>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="添加">
</td>
</tr>
</table>
</form>