zoukankan      html  css  js  c++  java
  • ThinkPHP RBAC权限管理机制

    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>
    If the copyright belongs to the longfei, please indicate the source!!!
  • 相关阅读:
    面向服务的体系架构 SOA(三) --- Zookeeper API、zkClient API的使用
    面向服务的体系架构 SOA(二) --- 服务的路由和负载均衡
    面向服务的体系架构 SOA(一) --- 基于TCP、HTTP协议的RPC
    eclipse集成dorado5插件
    java微信公众号开发token验证失败的问题及解决办法
    oracle使用中的一些问题
    JAVA设计模式之装饰者模式
    JAVA设计模式之观察者模式
    JDBC三层架构
    如何使用JDBC实现数据访问对象层(DAO)
  • 原文地址:https://www.cnblogs.com/longfeiPHP/p/4923044.html
Copyright © 2011-2022 走看看