Thinkphp下实现Rbac

Rbac,基于角色的权限管理系统,可以很好的管理后台,需要5张表,Thinkphp提供了4张,分别是,角色表,节点表,权限表,角色和用户的中间表。我们需要自己创建一张用户表。

TP提供的4张表:

CREATE TABLE IF NOT EXISTS `think_access` (
  `role_id` smallint(6) unsigned NOT NULL,
  `node_id` smallint(6) unsigned NOT NULL,
  `level` tinyint(1) NOT NULL,
  `module` varchar(50) DEFAULT NULL,
  KEY `groupId` (`role_id`),
  KEY `nodeId` (`node_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `think_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  DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `think_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  DEFAULT CHARSET=utf8 ;

CREATE TABLE IF NOT EXISTS `think_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;

我们需要把表前缀改成自己需要的,这里我改成hd_.

表创建好之后,首先写角色表,因为它和其他4个表都有关联,角色表和用户的多对多的关系,角色表和节点表也是多对多的关系

所以的表都是从添加开始的,:

1,我们先添加角色表,之后转到角色列表

php code

    //角色列表
    public function role(){
        $this->role=M('role')->select();
        
        $this->display();
    }
    //添加角色
    public function addRole(){
        $this->display();
    }
    //添加角色处理
    public function addRoleHandle(){
        if(M('role')->add(I('post.'))){                          //接受参数并添加进数据库
            $this->success('添加成功',U(MODULE_NAME.'/Rbac/role'));
        }else{
            $this->error('添加失败');
        }
    }

html

添加角色
<
form action='{:U(MODULE_NAME."/Rbac/addRoleHandle")}' method='post'> <table class='table'> <tr><td colspan='2' align='right'>添加角色</td></tr> <tr><td align='right'>角色名称</td><td><input type='text' name='name' /></td></tr> <tr><td align='right'>角色描述</td><td><input type='text' name='remark' /></td></tr> <tr><td align='right'>是否开启</td><td><input type='radio' name='status' value=1 checked='checked' />开启 <input type="radio" name='status' value=0>关闭</td></tr> <tr><td colspan='2' align='center'><input type='submit' value='添加' /></td></tr> </table> </form>
角色列表
<
table class='table'> <tr><th colspan='5'>角色列表</th></tr> <tr> <th>ID</th> <th>角色名称</th> <th>角色描述</th> <th>开启状态</th> <th>操作</th> </tr> <foreach name='role' item='v'> <tr> <th>{$v.id}</th> <th>{$v.name}</th> <th>{$v.remark}</th> <th><if condition='$v["status"]'>开启<else/>关闭</if></th> <th><a href='{:U(MODULE_NAME."/Rbac/access",array("id"=>$v["id"]))}'>权限配置</a></th> </tr> </foreach>

2 添加节点,之后转到节点表

php code

    //节点列表
    public function node(){
       $node= M('node')->order('id')->select();
       $this->node=node_merge($node);            //递归重组信息为多维数组, 目的是,pid和id相等的情况下,把pid的节点信息作为id节点信息的子节点压到id的节点信息中
                                                 //一个表的压缩,模型是指2个表直接的组合
       $this->display();
    }
    //添加节点
    public function addNode(){
        $this->level=I('get.level','1','intval');
        $this->pid=I('get.pid','0','intval');
        switch ($this->level){
            case 1:$this->title='应用';
            break;
            case 2:$this->title='控制器';
            break;
            case 3:$this->title='方法';
            break;
        }
        $this->display();
    }
    //添加节点处理
    public function addNodeHandle(){
        if(M('node')->add(I('post.'))){
            $this->success('添加成功',U(MODULE_NAME.'/Rbac/node'));
        }else{
            $this->error('添加失败');
        }
    }
添加节点
<
form action='{:U(MODULE_NAME."/Rbac/addNodeHandle")}' method='post'> <table class='table'> <tr><td colspan='2' align='right'>添加节点</td></tr> <tr> <td align='right'>{$title}名称</td><td><input type='text' name='name' /></td> </tr> <tr> <td align='right'>{$title}描述</td><td><input type='text' name='remark' /></td> </tr> <tr> <td align='right'>是否开启</td><td><input type='radio' name='status' checked='checked' value=1 />开启<input type='radio' name='status' value=0 />关闭</td> </tr> <tr><td colspan='2' align='center'><input type='submit' value='添加' /></td></tr> <input type='hidden' name='pid' value={$pid} /> <input type='hidden' name='level' value={$level} /> </table> </form>
节点列表
<
a href='{:U(MODULE_NAME."/Rbac/addNode")}'>[添加应用]</a><br/> <foreach name='node' item='v'> {$v.remark}<a href='{:U(MODULE_NAME."/Rbac/addNode",array("pid"=>$v["id"],"level"=>2))}'>【添加控制器】</a><br/> <foreach name='v.child' item='c'> {$c.remark}<a href='{:U(MODULE_NAME."/Rbac/addNode",array("pid"=>$c["id"],"level"=>3))}'>[添加方法]</a><br/> <foreach name='c.child' item='m'> {$m.remark}【<a href='#'>修改</a>】【<a href='#'>删除</a><br/> </foreach> </foreach> </foreach>

3,给角色配置权限

    //给角色配置权限
    public function access(){
        $field=array('id','remark','pid','level');
        $node=M('node')->field($field)->select();
        $this->rid=$_GET['id'];
        $access=M('access')->where(array('role_id'=>$_GET['id']))->getField('node_id',true);
        
        $this->node=node_merge($node,$access);     //显示用户原本就有的权限,把access压入每一个表中作为标记,1表示有,0表示没有
        $this->display();
    }
    //配置权限处理
    public function accessHandle(){
        $access=I('post.access');
        $arr=array();
        foreach ($access as $v){
            $res=explode('_',$v);
            
             $arr[]=array(
                'role_id'=>I('post.rid'),
                'node_id'=>$res[0],
                'level'=>$res[1], 
            );
        }
        $where=array('role_id'=>I('post.rid'));
        M('access')->where($where)->delete();            //先删除原有权限,再添加新的权限
        
          if(M('access')->addAll($arr)){
            $this->success('添加成功',U(MODULE_NAME.'/Rbac/role'));
        }else{
            $this->error('添加失败');
        }  
        
    }
配置权限
<
form action='{:U(MODULE_NAME."/Rbac/accessHandle")}' method='post'> <foreach name='node' item='v'> {$v.remark}<input type='checkbox' name='access[]' value='{$v["id"]}_1' <if condition='$v["access"]'>checked='checked'</if> /> <br/> <foreach name='v.child' item='c'> {$c.remark}<input type='checkbox' name='access[]' value='{$c["id"]}_2'<if condition='$c["access"]'>checked='checked'</if> /><br/> <foreach name='c.child' item='m'> {$m.remark}<input type='checkbox' name='access[]' value='{$m["id"]}_3'<if condition='$m["access"]'>checked='checked'</if> /><br/> </foreach> </foreach> </foreach> <input type='hidden' name='rid' value={$rid} /> <input type='submit' value='配置' /> </form>

4,添加用户,转到用户列表,添加用户的同时选择角色

//用户列表
    public function user(){
        $this->user=D('BlogRelation')->field('password',true)->relation(true)->select();//用户和角色的多对多关系,是为了在一个页面显示而建立的,
                                                                                        //如果要在一个页面显示角色所拥有的权限,页建立一个多对多的模型
        $this->display();
    }
    //添加用户
    public function addUser(){
        $this->role=M('role')->select();
        $this->display();
    }
    //添加用户处理
    public function addUserHandle(){
        $user=array(
            'username'=>I('username'),
            'password'=>I('password','',md5),
            'logintime'=>time(),
            'loginip'=>get_client_ip(),
        );
        $arr=array();
        if($user_id=M('user')->add($user)){
            foreach (I('post.id') as $v){
                
                $arr[]=array(
                    'user_id'=>$user_id,
                    'role_id'=>$v,
                );
                
            }
        }
        if(M('role_user')->addAll($arr)){
            
            $this->success('添加成功',U(MODULE_NAME.'/Rbac/user'));
        }else{
            $this->error('添加失败');
        }
        
        
    }
添加用户
<
body> <form action='{:U(MODULE_NAME."/Rbac/addUserHandle")}' method='post'> <table class='table'> <tr> <td colspan='2' align='right'>添加用户</td> </tr> <tr><td align='right'>用户名</td><td><input type='text' name='username' /></td></tr> <tr><td align='right'>用户密码</td><td><input type='password' name='password' /></td></tr> <tr><td align='right'>所属角色</td><td> <foreach name='role' item='v'> <input type='checkbox' name='id[]' value='{$v["id"]}' />{$v.name}({$v.remark}) </foreach> </td></tr> <tr><td colspan='2' align='center'><input type='submit' value='添加' /></td></tr> </table> </form>
用户列表

<
form> <table class='table'> <tr> <th>ID</th> <th>用户名</th> <th>上次登陆时间</th> <th>上次登陆IP</th> <th>锁定状态</th> <th>用户所属组别</th> <th>操作</th> </tr> <foreach name='user' item='v'> <tr> <td>{$v.id}</td> <td>{$v.username}</td> <td>{$v.logintime|date='Y-m-d H:i',###}</td> <td>{$v.loginip}</td> <td> <if condition='$v["lock"]'>锁定<else/>开启</if></td> <td> <if condition='$v["username"] eq "admin"'>超级管理员</if> <foreach name='v.role' item='r'> {$r.name}({$r.remark}) </foreach> </td> <td><a href='#'>锁定</a></td> </tr> </foreach> </table> </form>

配置信息

//Rbac配置
    'REAC_SUPERADMIN'=>'admin',    //超级管理员名称
    'ADMIN_AUTH_KEY'=>'superadmin', //超级管理员识别
    'USER_AUTH_ON'  =>true,        //是否开启验证
    'USER_AUTH_TYPE'=>1,           //验证类型(1:登陆验证 2:时时验证)
    'USER_AUTH_KEY'=>'uid',        //用户认证识别号
    'NOT_AUTH_MODULE'=>'Index,Login',         // 无需认证的控制器
    'NOT_AUTH_ACTION'=>'',         //无需认证的方法
    'RBAC_ROLE_TABLE'=>'hd_role',  // 角色表名称
    'RBAC_USER_TABLE'=>'hd_role_user',  //角色与用户的中间表名称
    'RBAC_ACCESS_TABLE'=>'hd_access',   //权限表名称
    'RBAC_NODE_TABLE'=>'hd_node',       //节点名称

最后,要通过Rbac类完成角色权限认证

       //用户权限配置
       $Rbac=new OrgUtilRbac();
       $Rbac::saveAccessList();
      // p($_SESSION);die;
    public function _initialize(){
        if(!isset($_SESSION[C('USER_AUTH_KEY')])){
            $this->redirect(MODULE_NAME.'/Login/index');
        }
       if(C('USER_AUTH_ON')){
            $RBAC= new OrgUtilRbac();
            $RBAC::AccessDecision()||$this->error('没有权限');
            
        }
    }

都是些没用的,浪费博客园的空间和流量了,这样可以基本完成角色权限系统,

原文地址:https://www.cnblogs.com/hhfhmf/p/4719818.html