ThinkPHP RBAC權限管理機制

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>
相關文章
相關標籤/搜索