RBAC是ThinkPHP很好用的後臺權限管理的,話很少說,實現方法以下,也方便之後本身查詢使用:php
一、新建4個數據庫表html
self_role權限表node
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的關係表(重點分析好這個表)session
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');
二、配置後臺配置文件/Admin/Confpost
'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',
三、公共控制器上進行驗證:ui
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 沒有開啓認證或者當前模塊不須要認證,則經過 } }
四、新建Public控制器PublicAction.class.phpthis
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('已經登出了'); } } }
五、創建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>
六、登出
<a href="__APP__/Public/logout">登出</a>