RBAC是ThinkPHP很好用的后台权限管理的,话不多说,实现方法如下,也方便以后自己查询使用:
1、新建4个数据库表
self_role权限表
CREATE TABLE `self_role` ( `id` smallint(6) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, `pid` smallint(6) DEFAULT NULL, `status` tinyint(1) unsigned DEFAULT NULL, `remark` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`), KEY `pid` (`pid`), KEY `status` (`status`) ) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; INSERT INTO `self_role` VALUES ('1', '超级管理员', '0', '1', '超级管理权限'); INSERT INTO `self_role` VALUES ('2', '普通管理员', '0', '1', '普通管理权限'); INSERT INTO `self_role` VALUES ('3', '注册用户', '0', '1', '注册管理权限');
self_role_user表:权限(self_role)与用户表(self_user)的关系表
CREATE TABLE `self_role_user` ( `role_id` mediumint(9) unsigned DEFAULT NULL, `user_id` char(32) DEFAULT NULL, KEY `group_id` (`role_id`), KEY `user_id` (`user_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; INSERT INTO `self_role_user` VALUES ('1', '3'); INSERT INTO `self_role_user` VALUES ('2', '4');
self_node表:权限分配表
CREATE TABLE `self_node` ( `id` smallint(6) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, `title` varchar(50) DEFAULT NULL, `status` tinyint(1) DEFAULT '0', `remark` varchar(255) DEFAULT NULL, `sort` smallint(6) unsigned DEFAULT NULL, `pid` smallint(6) unsigned NOT NULL, `level` tinyint(1) unsigned NOT NULL, PRIMARY KEY (`id`), KEY `level` (`level`), KEY `pid` (`pid`), KEY `status` (`status`), KEY `name` (`name`) ) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=utf8; INSERT INTO `self_node` VALUES ('1', 'Admin', '后台项目', '1', '项目权限', '0', '0', '1'); INSERT INTO `self_node` VALUES ('2', 'Index', '默认控制模块', '1', '控制器', '0', '1', '2'); INSERT INTO `self_node` VALUES ('3', 'index', '默认操作', '1', '操作动作', '0', '2', '3'); INSERT INTO `self_node` VALUES ('4', 'User', '用户控制模块', '1', '控制器', '0', '1', '2'); INSERT INTO `self_node` VALUES ('5', 'Section', '单元控制模块', '1', '控制器', '0', '1', '2'); INSERT INTO `self_node` VALUES ('6', 'index', '用户默认操作', '1', '操作动作', '0', '4', '3'); INSERT INTO `self_node` VALUES ('7', 'add', '用户添加操作', '1', '操作动作', '0', '4', '3'); INSERT INTO `self_node` VALUES ('8', 'index', '单元默认操作', '1', '操作动作', '0', '5', '3'); INSERT INTO `self_node` VALUES ('9', 'add', '单元添加操作', '1', '操作动作', '0', '5', '3');
self_access表:self_node与self_role的关系表(重点分析好这个表)
CREATE TABLE `self_access` ( `role_id` smallint(6) unsigned NOT NULL, `node_id` smallint(6) unsigned NOT NULL, `level` tinyint(1) NOT NULL, `pid` varchar(50) DEFAULT NULL, KEY `groupId` (`role_id`), KEY `nodeId` (`node_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; INSERT INTO `self_access` VALUES ('1', '1', '1', '0'); INSERT INTO `self_access` VALUES ('2', '1', '1', '0'); INSERT INTO `self_access` VALUES ('1', '2', '2', '1'); INSERT INTO `self_access` VALUES ('2', '2', '2', '1'); INSERT INTO `self_access` VALUES ('2', '3', '3', '2'); INSERT INTO `self_access` VALUES ('1', '3', '3', '2'); INSERT INTO `self_access` VALUES ('2', '4', '2', '1'); INSERT INTO `self_access` VALUES ('1', '4', '2', '1'); INSERT INTO `self_access` VALUES ('1', '6', '3', '4'); INSERT INTO `self_access` VALUES ('2', '6', '3', '4'); INSERT INTO `self_access` VALUES ('1', '7', '3', '4');
2、配置后台配置文件/Admin/Conf
'USER_AUTH_ON'=>true,//开启RBAC权限认证 'USER_AUTH_TYPE'=>1,//使用session进行标记 'USER_AUTH_KEY'=>'authId',//设置session标记名称 'ADMIN_AUTH_KEY'=>'administrator',//设置管理员用户标记 'USER_AUTH_MODEL'=>'User',//验证用户的表模型 //'AUTH_PWD_ENCODER'=>'md5',//用户认证密码加密方式 'USER_AUTH_GATEWAY'=>'/Public/login',//默认的认证网关 'NOT_AUTH_MODULE'=>'Public',//默认不需要认证的控制模块 'REQUIRE_AUTH_MODULE'=>'',//默认需要认证的模块 'NOT_AUTH_ACTION'=>'',//默认不需要认证的动作 'REQUIRE_AUTH_ACTION'=>'',//默认需要认证的动作 'GUEST_AUTH_ON'=>false,//是否开启游客授权访问 'GUEST_AUTH_ID'=>0,//游客标记 'RBAC_ROLE_TABLE'=>'self_role', 'RBAC_USER_TABLE'=>'self_role_user', 'RBAC_ACCESS_TABLE'=>'self_access', 'RBAC_NODE_TABLE'=>'self_node',
3、公共控制器上进行验证:
class CommonAction extends Action{ function _initialize(){ header('Content-Type:text/html;charset=utf-8'); //第一步:判断是否开启了认证 判断当前模块是否需要认证 if(C('USER_AUTH_ON') && !in_array(MODULE_NAME,explode(',',C('NOT_AUTH_MODULE')))){ //第二步:开启认证,导入RBAC类 import('ORG.Util.RBAC'); //判断不通过认证 if(!RBAC::AccessDecision()){ //第三步:当认证不通过是该如何处理 //判断session中是否存放了用户标记 if(!$_SESSION[C('USER_AUTH_KEY')]){ //用户没有登陆 $this->assign('jumpUrl',__APP__.'/Public/login'); $this->error('对不起,您没有登陆,请登录'); }//else //代表用户已经登陆 //判断是否开启了游客登陆功能 if(C('GUEST_AUTH_ON')){ //开启则跳转到游客页面 } $this->error('对不起您没有操作权限'); }//else 认证通过了 }//else 没有开启认证或者当前模块不需要认证,则通过 } }
4、新建Public控制器PublicAction.class.php
class PublicAction extends Action{ function login(){ $this->display(); } function verify(){ import('ORG.Util.Image'); Image::buildImageVerify(); } function checklogin(){ //检查表单数据的有效性 用户名 密码 验证码必须填写 if(empty($_POST['username'])){ $this->error('用户名必须填写'); } if(empty($_POST['password'])){ $this->error('密码必须填写'); } if(empty($_POST['verify'])){ $this->error('验证码必须填写'); } //整理需要用户验证的数据 $map = array(); $map['username'] = $_POST['username']; $map['active'] = array('gt',0); if($_SESSION['verify'] !== md5($_POST['verify'])){ $this->error('验证码输入错误'); } //RBAC验证 import('ORG.Util.RBAC'); //提取用户数据 $user = RBAC::authenticate($map); //判断是否能提取用户数据 if(empty($user)){ $this->error('用户不存在或者被禁用'); }else{ //如果数据提取成功,判断密码是否输入正确 //注意:post中的密码要经过md5加密后再跟数据库中的密码进行比较 if($user['password'] != $_POST['password']){ $this->error('用户密码输入错误'); }//else 密码验证通过 //保存session的会话标识,用来后面判断用户已经登录的状态 $_SESSION[C('USER_AUTH_KEY')] = $user['id'];//把用户id存入session //存储后面需要用到的数据,如email 和登录时间等等 $_SESSION['email'] = $user['email']; //超级管理身份验证 if($user['admin'] == 'admin'){ $_SESSION[C('ADMIN_AUTH_KEY')] = true; } //保存本用户的登录信息 $u = M('User'); $lastdate = date('Y-m-d H:i:s'); $row['id'] = $user['id']; $row['last_login_date'] = $lastdate; $u->save($row); //缓存访问权限 RBAC::saveAccessList(); //页面登录成功的跳转 $this->assign('jumpUrl',__APP__.'/Index/index'); $this->success('登录成功'); } } function logout(){ //判断用户是否正在登录 if(!empty($_SESSION[C('USER_AUTH_KEY')])){ //正在登录中.. unset($_SESSION[C('USER_AUTH_KEY')]); $_SESSION = array(); session_destroy(); $this->assign('jumpUrl',__URL__.'/login'); $this->success('登出成功'); }else{ //已经登出了 $this->error('已经登出了'); } } }
5、建立success.html和login.html模板
success.html
<!doctype html> <html> <head> <meta charset="utf-8"> <title>selfcms 系统信息提示</title> </head> <body> <h1>{$msgTitle}</h1> <h2>{$message}</h2> <h3> 系统将在<font color="#FF0000">{$waitSecond}</font>秒后自动跳转,如果不想等待,请 <a href="{$jumpUrl}">点击这里</a>跳转 </h3> </body> </html>
login.html
<!doctype html> <html> <head> <meta charset="utf-8"> <title>login</title> </head> <body> <form action="__URL__/checklogin" method="post"> 用户名:<input type="text" name="username" /><br> 密码:<input type="password" name="password" /><br> 验证码:<input type="text" name="verify" /><img src="__URL__/verify" alt="验证码" /><br> <input type="submit" value="登录" /> </form> </body> </html>
6、登出
<a href="__APP__/Public/logout">登出</a>