RBAC:Role Based Access Control:基于角色的访问控制 需求:
1. 权限、角色、管理员
2 权限管理【无限级】
注意:权限会被分配给角色,不是管理员!
3 角色列表
添加角色时要给角色分配权限:
4
管理员列表
5 系统中默认有一个超级管理员并且不能被删除【无法分配权限,拥有所有的权限】
6 只有登录了才能进行后台
7 后台左侧只显示当前管理员有权限访问的按钮
实际操作:
- 建表
三个主表两个中间表:
/************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. 再生成管理和角色
修改管理员管理的功能
- 管理员密码加密 在admin模型添加
// 添加前
protected function _before_insert(&$data, $option)
{
$data[‘password‘]=md5($data[‘password‘]);
}
- 超级管理员不能被删除
// 删除前
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>
- 修改管理员时,如果密码留空就不修改密码
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‘]);
}
权限和角色的关系的代码
用到的表:
实际操作:
- 在添加角色的表单中制作权限列表
//取出所有的权限
$priModel=D(‘privilege‘);
$priData=$priModel->getTree();
// 设置页面中的信息
$this->assign(array(
‘priData‘=>$priData,
‘_page_title‘ => ‘添加角色‘,
‘_page_btn_name‘ => ‘角色列表‘,
‘_page_btn_link‘ => U(‘lst‘),
));
- 在表单中循环输出
- 提交表单之后循环选中的每个权限插入到角色权限中间表中
修改角色模型在添加之后:
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‘],
));
}
}
- 在角色列表中,再添加一列列出这个角色所拥有的所有的权限名称
修改角色模型中的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;