RBAC:Role Based Access Control:基于角色的访问控制 需求:

    

1. 权限、角色、管理员

 

2   权限管理【无限级】

 

注意:权限会被分配给角色,不是管理员!

 

3 角色列表

 

添加角色时要给角色分配权限:

 4

管理员列表

   

5    系统中默认有一个超级管理员并且不能被删除【无法分配权限,拥有所有的权限】

 6    只有登录了才能进行后台

7    后台左侧只显示当前管理员有权限访问的按钮

 

实际操作:

 

  1. 建表

三个主表两个中间表:

   

/************RBAC权限表***********/

drop table if exists p40_privilege;
create table p40_privilege
(
id mediumint unsigned not null auto_increment comment 'Id',
pri_name varchar(30) not null comment '权限名称',
module_name varchar(30) not null default '' comment '模块名称',
controller_name varchar(30) not null default '' comment '控制器名称',
action_name varchar(30) not null default '' comment '方法名称',
parent_id mediumint unsigned not null default '0' comment '上级权限Id',
primary key(id)
)engine =InnoDB default charset=utf8 comment '权限';


drop table if exists p40_role_pri;
create table p40_role_pri
(
pri_id mediumint unsigned not null comment '权限id',
role_id mediumint unsigned not null comment '角色id',
key pri_id(pri_id),
key role_id(role_id)
)engine=InnoDB default charset=utf8 comment '角色权限';


drop table if exists p40_role;
create table p40_role
(
id mediumint unsigned not null auto_increment comment 'id',
role_name varchar(30) not null comment '角色名称',
primary key(id)

)engine=InnoDB default charset utf8 comment '角色';


drop table if exists p40_admin_role;
create table p40_admin_role
(
admin_id mediumint unsigned not null comment '管理员id',
role_id mediumint unsigned not null comment '角色id',
key admin_id(admin_id),
key role_id(role_id)
)engine =InnoDB default charset=utf8 comment '管理员角色';

drop table if exists p40_admin;
create table p40_admin
(
id mediumint unsigned not null auto_increment comment 'id',
username varchar(30) not null comment '用户名',
password char(32) not null comment '密码',
primary key(id)
)engine=InnoDB default charset utf8 comment '管理员';

insert into p40_admin(username,password) values('admin',md5('admin'));

 

说明:TP框架中自带一个RBAC的类:也是要使用五张表,TP只提供了五个表和一个类,这个类只提供了将来对五个表的查询,但是这五个表的操作还需要我们自己写!不需要使用TP的,因为它就没有提供什么东西,还是需要自己写。

 

 

2  使用GII直接生成三个主表的代码,表间关系的代码需要我们自己添加完成!!

 

生成权限列表:

   

修改配置文件:

设置为生成递归的代码

   

'tableName' => 'p40_privilege', // 表名
'tableCnName' => '权限', // 表的中文名
'moduleName' => 'Admin', // 代码生成到的模块
'withPrivilege' => FALSE, // 是否生成相应权限的数据
'topPriName' => '', // 顶级权限的名称
'digui' => 1, // 是否无限级(递归)
'diguiName' => 'pri_name', // 递归时用来显示的字段的名字,如cat_name(分类名称)
'pk' => 'id', // 表中主键字段名称
/********************* 要生成的模型文件中的代码 ******************************/
// 添加时允许接收的表单中的字段
'insertFields' => "array('pri_name','module_name','controller_name','action_name','parent_id')",
// 修改时允许接收的表单中的字段
'updateFields' => "array('id','pri_name','module_name','controller_name','action_name','parent_id')",
'validate' => "

 

去掉搜索

 

/**************** 搜索字段的配置 **********************/
'search' => array(),

 

生成代码:

 p40_privilege.php

 

到此无限级权限完成!

 

2.2. 再生成管理和角色

 

 

修改管理员管理的功能

  

  1. 管理员密码加密  在admin模型添加
  2.  

 

// 添加前
protected function _before_insert(&$data, $option)
{
$data['password']=md5($data['password']);
}

  1. 超级管理员不能被删除

  

// 删除前
protected function _before_delete($option)
{
if($option($option['where']['id']) == 1 )
{
$this->error = '超级管理员无法删除';
return FALSE;
}
}

 

 

超级管理员不显示删除按钮

  

<td align="center">
<a href="<?php echo U('edit?id='.$v['id'].'&p='.I('get.p')); ?>" title="编辑">编辑</a>
<?php if($v['id'] >1) : ?>
|
<a href="<?php echo U('delete?id='.$v['id'].'&p='.I('get.p')); ?>" onclick="return confirm('确定要删除吗?');" title="移除">移除</a>

<?php endif; ?>
</td>

 

  1. 修改管理员时,如果密码留空就不修改密码

3.1 修改表单验证规则,修改时可以为空,添加时不能为空

   

array('username', 'require', '用户名不能为空!', 1, 'regex', 3),
array('username', '1,30', '用户名的值最长不能超过 30 个字符!', 1, 'length', 3),
//第6个参数:规则什么时候生效:1 添加时生效 2 修改时生效 3 所有情况都生效
array('password', 'require', '密码不能为空!', 1, 'regex',1),

 

现在可以不填写密码了,但是被修改为空:

 

修改之前判断一下即可:

   

// 修改前
protected function _before_update(&$data, $option)
{
if($data['password'])
$data['password']=md5($data['password']);
else
unset($data['password']);
}

 

 

权限和角色的关系的代码

  

用到的表:

 

实际操作:

  1. 在添加角色的表单中制作权限列表

  

//取出所有的权限
$priModel=D('privilege');
$priData=$priModel->getTree();

// 设置页面中的信息
$this->assign(array(
'priData'=>$priData,
'_page_title' => '添加角色',
'_page_btn_name' => '角色列表',
'_page_btn_link' => U('lst'),
));

  1. 在表单中循环输出
  1. 提交表单之后循环选中的每个权限插入到角色权限中间表中

  

修改角色模型在添加之后:

  

public function _after_insert($data,$opiton)
{
$priId=I('post.pri_id');
$rpModel=D('role_pri');
foeach($priId as $v)
{
$rpModel->add(array(
'pri_id'=>$v,
'role_id'=>$data['id'],
));
}
}

  1. 在角色列表中,再添加一列列出这个角色所拥有的所有的权限名称

修改角色模型中的search方法

$data['data'] = $this->alias('a')
->field('a.*,c.pri_name')
->join('left join __ROLE_PRI__ b on a.id = b.role_id
left join __PRIVILEGE__ c on b.pri_id=c.id')
->where($where)
->limit($page->firstRow.','.$page->listRows)
->select();
return $data;