YII2框架RBAC 实例运用

来源:互联网 发布:电脑该网络存储 编辑:程序博客网 时间:2024/06/06 01:36

YII2框架RBAC 自己开发(权限控制)实例运用

原创 2016年11月10日 16:01:42

1、首先说一下什么是RBAC

基于角色的访问控制(Role-Based Access Control),作为传统访问控制(自主访问,强制访问)的有前景的受到广泛的关注,在RBAC中,权限与角色相关联,用户通过角色的成员得到这些角色的权限。这就极大地简化了权限的管理。在一个组织中,角色是为了完成各种工作而创造,用户则依据他的责任和资格来被指派响应的角色,用户可以很容易地从一个角色被指派到另一个角色。角色可依新的需求和系统的合并并赋予新的权限,而权限也可根据需要而从某角色中回收。角色与角色的关系可以建立起来以囊括更广泛的客观情况。

2、测试中我们可以做一个简单的登录,将用户名和id存入到session中,方便以后的使用

3、yii框架中的权限分配

我们在学习PHP的过程中应该对TP框架中的RBAC很熟悉,其实框架之间的内容大多数都是相同的,下面让我们来看一下yii框架中的RBAC。

配置RBAC

在开始定义授权数据和执行存取检查之前,需要先配置应用组件yii/base/Application::authManager。yii提供了两套授权管理器;yii/rbac/phpManager和yii/rbac/DbManager。牵着使用PHP脚本存放授权数据,而后者使用数据库存放授权数据。如果你的应用不要求大量的动态角色和权限管理,你可以考虑使用前者。

下面是两个文件的位置



配置在frontend/backend文件夹,config文件夹下main.php


或者


有关yii2使用RBAC地址:http://www.yiifans.com/forum.php?mod=viewthread&tid=11244


我们此时用自己的方法套用YII2框架实现RBAC

RBAC实现思路:

所需表:
       用户表
       角色表
       用-角派生表
       节点表
       节-角的派生表

大致步骤:
1、首先根据用户id 查询用-角派生表 查出角色id
2、在根据角色id 查询 节-角派生表 查出改角色对应节点id 中的控制器和方法

3、再用当前的的控制器和方法进行比对 如果没有就权限给出提示


难点:表关系的处理、查询语句、以及节点赋权时 多选框 点击一级其余子级选中、点击子级父级选中



笔者运用的ACE后台模板

效果展示:



节点列表


角色列表


角色节点赋权


用户角色赋权



代码实例:

common控制器

<?phpnamespace frontend\controllers;header("content-type:text/html;charset=utf-8");use Yii;use yii\base\InvalidParamException;use yii\web\BadRequestHttpException;use yii\web\Controller;use yii\filters\VerbFilter;use yii\filters\AccessControl;use common\models\LoginForm;use frontend\models\PasswordResetRequestForm;use frontend\models\ResetPasswordForm;use frontend\models\SignupForm;use frontend\models\ContactForm;use yii\db\Query;class CommonController extends Controller{    /**     * @param \yii\base\Action $action     * @return bool     * @throws BadRequestHttpException     */    public function beforeAction($action){        $session=\Yii::$app->session;        $user_session=$session->get('user');        //判断是否有登录session        if(!isset($user_session)){            echo "<script>alert('请先登录');location.href='index.php?r=login/login'</script>";die;        }        //设置超级管理员        if($user_session=="admin"){            return true;        }        //判断权限        $ctl=Yii::$app->controller->id;     //获取当前访问的控制器        $action=Yii::$app->controller->action->id;     //获取当前访问的方法        //当访问后台是首页权限是公共的        if($ctl=="admin" && $action=="index"){            return true;        }        $id_session=$session->get('id');       //接到用户登录时存的id        $sql="select  rn.node_id,n.controller,n.action  from role_node as rn left join node as n on  rn.node_id=n.node_id where role_id in(SELECT role_id from  user_role where user_id=$id_session) group by rn.node_id";        $rows=Yii::$app->db->createCommand($sql)->queryAll();    //查询出该角色的权限        if($rows){            foreach($rows as $key => $val){                if($val['controller']==$ctl && $val['action']==$action){                    return true;                }            }            echo "<script>alert('抱歉,您的权限不够');location.href='index.php?r=admin/index'</script>";            return false;        }else{            echo "<script>alert('抱歉,您的权限不够');location.href='index.php?r=admin/index'</script>";        }        if (!parent::beforeAction($action)) {            return false;        }        return true;    }}
用户控制器

<?phpnamespace frontend\controllers;use Yii;use yii\web\Controller;use yii\db\Query;use yii\data\Pagination;class UsersController extends CommonController{    public $layout = 'admin';    /**显示页面     * @return void     */    public function actionShow(){        $query = new Query();        //查询出所有的数据        $userList = $query->from('user')->where(['is_delete'=>0])->all();        //统计数据个数        $count = count($userList);        //实例化分页类        $pagination = new Pagination(['totalCount' => $count]);        $pagination->setPageSize(2 );        $data = $query->offset($pagination->offset)->limit($pagination->limit)->all();        return $this->render('show', ['data' => $data, 'pagination' => $pagination,]);    }    /**     * 删除     * @return void     */    public function actionDel()    {        $db = Yii::$app->db;        $id = Yii::$app->request->get('user_id');        $res = $db->createCommand()->update('user',['is_delete'=>1],['user_id'=>$id])->execute();        if($res)        {            echo "<script>alert('删除成功');location.href='index.php?r=users/show'</script>";        }else{            echo "<script>alert('删除失败');location.href='index.php?r=users/show'</script>";       }    }    /**     *添加     * @return void     */    public function actionAdd(){        $request = YII::$app->request;        if($request->isPost) {            $user_name = $request->post('user_name');            $user_pwd = $request->post('user_pwd');            $user_time=date("Y-m-d H:i:s",time());            $res=Yii::$app->db->createCommand()->insert('user', ['user_name' => $user_name,'user_pwd'=>$user_pwd,'user_time'=>$user_time])->execute();            if($res){                echo "<script>alert('添加成功');location.href='index.php?r=users/show'</script>";            }else{                echo "<script>alert('添加失败');location.href='index.php?r=users/show'</script>";            }        }else{            return $this->render('add');        }    }    /**     * 修改数据     * @return void     */    public function actionUpda()    {        $request = YII::$app->request;        if($request->isPost){            $user_name=$request->post('user_name');            $user_pwd=$request->post('user_pwd');            $user_id=$request->post('user_id');            $res=Yii::$app->db->createCommand()->update('user', ['user_name' => $user_name,'user_pwd'=>$user_pwd], "user_id = $user_id")->execute();            if($res){                echo "<script>alert('修改成功');location.href='index.php?r=users/show'</script>";            }else{                echo "<script>alert('修改失败');location.href='index.php?r=users/show'</script>";            }        }        if($request->get('user_id')){            $id=$request->get('user_id');            $data = Yii::$app->db->createCommand("SELECT * FROM user WHERE user_id=$id")->queryOne();            return $this->render('upda', ['userInfo' => $data]);        }    }    /**用户角色赋权     * @return string     * @throws \yii\db\Exception     */    public function actionAuthority(){        $request = YII::$app->request;        $db = Yii::$app->db;        if($request->isPost){            $request->post();            $role_ids= $request->post('role_id');            $user_id= $request->post('user_id');            //查询派生表中数据            $sql="select * from user_role where user_id=$user_id";            $user_role=Yii::$app->db->createCommand($sql)->queryAll();            if($user_role){                //删除派生表中原有数据                $re=Yii::$app->db->createCommand()->delete('user_role', "user_id = $user_id")->execute();                //判断是否接到值                if($role_ids){                    foreach($role_ids as $v){                        $res=Yii::$app->db->createCommand()->insert('user_role', ['user_id' => $user_id,'role_id'=>$v])->execute();                    }                    if($res){                        echo "<script>alert('角色赋权成功');location.href='index.php?r=users/show'</script>";die;                    }else{                        echo "<script>alert('角色赋权失败');location.href='index.php?r=users/show'</script>";die;                    }                }else{                    echo "<script>alert('清除所有角色');location.href='index.php?r=users/show'</script>";die;                }            }else{                if($role_ids){                    foreach($role_ids as $v){                        $res=Yii::$app->db->createCommand()->insert('user_role', ['user_id' => $user_id,'role_id'=>$v])->execute();                    }                    if($res){                        echo "<script>alert('角色赋权成功');location.href='index.php?r=users/show'</script>";die;                    }else{                        echo "<script>alert('角色赋权失败');location.href='index.php?r=users/show'</script>";die;                    }                }else{                    echo "<script>alert('清除所有角色');location.href='index.php?r=users/show'</script>";die;                }            }        }        if($request->isGet){            //查询角色表            $query = new Query();            //查询出所有的数据            $roleList = $query->from('role')->where(['is_delete'=>0])->all();            $user_id = Yii::$app->request->get('user_id');            //查询用户拥有角色            $sql="select * from user_role where user_id=$user_id";            $user_role=Yii::$app->db->createCommand($sql)->queryAll();            $arr=array();            foreach($user_role as $v){                $arr[]=$v['role_id'];            }            //前台多选框选中字段添加            foreach($roleList as $k=>$val){                if(in_array($val['role_id'],$arr)){                    $roleList[$k]['check']="check";                }else{                    $roleList[$k]["check"]="false";                }            }            return $this->render('authority',['roleList'=>$roleList,'user_id'=>$user_id,'user_role'=>$user_role]);        }    }}
角色控制器

<?phpnamespace frontend\controllers;use Yii;use yii\web\Controller;use yii\db\Query;use yii\data\Pagination;class RoleController extends CommonController{    public $layout = 'admin';    public function actionShow(){        $query = new Query();        //查询出所有的数据        $userList = $query->from('role')->where(['is_delete'=>0])->all();        //统计数据个数        $count = count($userList);        //实例化分页类        $pagination = new Pagination(['totalCount' => $count]);        $pagination->setPageSize(2 );        $data = $query->offset($pagination->offset)->limit($pagination->limit)->all();        return $this->render('show', ['data' => $data, 'pagination' => $pagination,]);    }    /**     * 删除     * @return void     */    public function actionDel()    {        $db = Yii::$app->db;        $id = Yii::$app->request->get('role_id');        $res = $db->createCommand()->update('role',['is_delete'=>1],['role_id'=>$id])->execute();        if($res)        {            echo "<script>alert('删除成功');location.href='index.php?r=role/show'</script>";        }else{            echo "<script>alert('删除失败');location.href='index.php?r=role/show'</script>";        }    }    /**     * 修改数据     * @return [type] [description]     */    public function actionUpda()    {        $request = YII::$app->request;        if($request->isPost){            $role_name=$request->post('role_name');            $role_desc=$request->post('role_desc');            $role_start=$request->post('role_start');            $role_id=$request->post('role_id');            $res=Yii::$app->db->createCommand()->update('role', ['role_name' => $role_name,'role_desc'=>$role_desc,'role_start'=>$role_start], "role_id = $role_id")->execute();            if($res){                echo "<script>alert('修改成功');location.href='index.php?r=role/show'</script>";            }else{                echo "<script>alert('修改失败');location.href='index.php?r=role/show'</script>";            }        }        if($request->get('role_id')){            $id=$request->get('role_id');            $data = Yii::$app->db->createCommand("SELECT * FROM role WHERE role_id=$id")->queryOne();            return $this->render('upda', ['roleInfo' => $data]);        }    }    /**添加角色     * @return string     * @throws \yii\db\Exception     */    public function actionAdd(){        $request = YII::$app->request;        if($request->isPost){            $role_name=$request->post('role_name');            $role_desc=$request->post('role_desc');            $role_start=$request->post('role_start');            $role_time=date("Y-m-d H:i:s",time());            $res=Yii::$app->db->createCommand()->insert('role', ['role_name' => $role_name,'role_desc'=>$role_desc,'role_start'=>$role_start,'role_time'=>$role_time])->execute();            if($res){                echo "<script>alert('添加成功');location.href='index.php?r=role/show'</script>";            }else{                echo "<script>alert('添加失败');location.href='index.php?r=role/show'</script>";            }        }else{            return $this->render('add');        }    }    /**角色节点赋权     * @return string     * @throws \yii\db\Exception     */    public function actionAuthority(){        $request = YII::$app->request;        if($request->isPost){            $request->post();            $node_ids= $request->post('node_id');            $role_id= $request->post('role_id');            //查询派生表中数据            $sql="select * from role_node where role_id=$role_id";            $role_node=Yii::$app->db->createCommand($sql)->queryAll();            if($role_node){                //删除派生表中原有数据                $re=Yii::$app->db->createCommand()->delete('role_node', "role_id = $role_id")->execute();                //判断是否接到值                if($node_ids){                    foreach($node_ids as $v){                        $res=Yii::$app->db->createCommand()->insert('role_node', ['role_id' => $role_id,'node_id'=>$v])->execute();                    }                    if($res){                        echo "<script>alert('节点赋权成功');location.href='index.php?r=role/show'</script>";die;                    }else{                        echo "<script>alert('节点赋权失败');location.href='index.php?r=role/show'</script>";die;                    }                }else{                    echo "<script>alert('清除所有节点');location.href='index.php?r=role/show'</script>";die;                }            }else{                if($node_ids){                    foreach($node_ids as $v){                        $res=Yii::$app->db->createCommand()->insert('role_node', ['role_id' => $role_id,'node_id'=>$v])->execute();                    }                    if($res){                        echo "<script>alert('节点赋权成功');location.href='index.php?r=role/show'</script>";die;                    }else{                        echo "<script>alert('节点赋权失败');location.href='index.php?r=role/show'</script>";die;                    }                }else{                    echo "<script>alert('清除所有节点');location.href='index.php?r=role/show'</script>";die;                }            }        }        if($request->isGet){            $id = Yii::$app->request->get('role_id');            //查询出所有节点            $query = new Query();            //查询出所有的数据            $nodeList = $query->from('node')->all();            $nodeLists=$this->sort_a($nodeList);            //查询出派生表中角色所定义的节点id            $role_node= Yii::$app->db->createCommand("SELECT * FROM role_node where role_id=$id")->queryAll();            //循环两个数组将角色对应的节点增加选中字段            $arr=array();            foreach($role_node as $v){                $arr[]=$v['node_id'];            }            foreach($nodeLists as $k=>$val){                if(in_array($val['node_id'],$arr)){                    $nodeLists[$k]['check']="check";                }else{                    $nodeLists[$k]['check']="false";                }            }            return $this->render('authority',['nodeLists'=>$nodeLists,'role_id'=>$id]);        }    }    /** 递归     * @param 列表数据     * @param int 父类id     * @param int 间隔     * @return array     */    public function sort_a($res,$sid=0,$level=0){        static $arr=array();        foreach($res as $key=>$val){            if($val['parent_id']==$sid){                $val['level']=str_repeat("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;",$level);                $arr[]=$val;                $this->sort_a($res,$val['node_id'],$level+1);            }        }        return $arr;    }}


节点控制器

<?phpnamespace frontend\controllers;use Yii;use yii\web\Controller;use yii\db\Query;use yii\data\Pagination;class NodeController extends CommonController{    public $layout = 'admin';    public function actionShow(){        $query = new Query();        //查询出所有的数据        $nodeList = $query->from('node')->all();        $nodeLists=$this->sort_a($nodeList);        return $this->render('show', ['data' => $nodeLists]);    }    /** 递归     * @param 列表数据     * @param int 父类id     * @param int 间隔     * @return array     */    public function sort_a($res,$sid=0,$level=0){        static $arr=array();        foreach($res as $key=>$val){            if($val['parent_id']==$sid){                $val['level']=str_repeat("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;",$level);                $arr[]=$val;                $this->sort_a($res,$val['node_id'],$level+1);            }        }        return $arr;    }    /**     * 删除     * @return void     */    public function actionDel()    {        $db = Yii::$app->db;        $id = Yii::$app->request->get('node_id');        $sql="select * from node where parent_id = $id";        $data = Yii::$app->db->createCommand("$sql")->queryAll();        if($data){            echo "<script>alert('该目录下有子类不能删除');location.href='?r=node/show';</script>";die;        }        $res=Yii::$app->db->createCommand()->delete('node', "node_id = $id")->execute();        if($res)        {            echo "<script>alert('删除成功');location.href='index.php?r=node/show'</script>";        }else{            echo "<script>alert('删除失败');location.href='index.php?r=node/show'</script>";        }    }    /**     * 修改数据     * @return void     */    public function actionUpda()    {        $request = YII::$app->request;        if($request->isPost){            $node_title=$request->post('node_title');            $controller=$request->post('controller');            $action=$request->post('action');            $parent_id=$request->post('parent_id');            $node_id=$request->post('node_id');            $res=Yii::$app->db->createCommand()->update('node', ['node_title' => $node_title,'controller'=>$controller,'action'=>$action,'parent_id'=>$parent_id], "node_id = $node_id")->execute();            if($res){                echo "<script>alert('修改成功');location.href='index.php?r=node/show'</script>";            }else{                echo "<script>alert('修改失败');location.href='index.php?r=node/show'</script>";            }        }        if($request->get('node_id')){            $query = new Query();            //查询出所有的数据            $nodeList = $query->from('node')->all();            $nodeLists=$this->sort_a($nodeList);            $id=$request->get('node_id');            $data = Yii::$app->db->createCommand("SELECT * FROM node WHERE node_id=$id")->queryOne();            return $this->render('upda', ['nodeInfo' => $data,'nodelist'=>$nodeLists]);        }    }    /**节点添加     * @return string     * @throws \yii\db\Exception     */    public function actionAdd(){        $query = new Query();        //查询出所有的数据        $nodeList = $query->from('node')->all();//        print_R($nodeList);exit;        $nodeLists=$this->sort_a($nodeList);        $request = YII::$app->request;        if($request->isPost){//            print_r( $request->post());exit;            $node_title=$request->post('node_title');            $controller=$request->post('controller');            $action=$request->post('action');            $parent_id=$request->post('parent_id');            $res=Yii::$app->db->createCommand()->insert('node', ['node_title' => $node_title,'controller'=>$controller,'action'=>$action,'parent_id'=>$parent_id])->execute();            if($res){                echo "<script>alert('添加成功');location.href='index.php?r=node/show'</script>";            }else{                echo "<script>alert('添加失败');location.href='index.php?r=node/show'</script>";            }        }else{            return $this->render('add',['nodelist'=>$nodeLists]);        }    }}

显示页面就不一一展示了,笔者只将用户赋角和角色赋节点两个页面展示

1、用户赋角

<div class="main-content">    <div class="breadcrumbs" id="breadcrumbs">        <script type="text/javascript">            try{ace.settings.check('breadcrumbs' , 'fixed')}catch(e){}        </script>        <ul class="breadcrumb">            <li>                <i class="icon-home home-icon"></i>                <a href="#">角色授权</a>            </li>            <li class="active">控制台</li>        </ul><!-- .breadcrumb -->        <div class="nav-search" id="nav-search">            <form class="form-search">                        <span class="input-icon">                            <input type="text" placeholder="Search ..." class="nav-search-input" id="nav-search-input" autocomplete="off" />                            <i class="icon-search nav-search-icon"></i>                        </span>            </form>        </div><!-- #nav-search -->    </div>    <div class="page-content">        <div class="page-header">            <h1>                权限管理功能                <small>                    <i class="icon-double-angle-right"></i>                    角色授权                </small>            </h1>        </div>        <!-- /.page-header -->        <!-- 添加HTML -->        <center>            <table>                <form action="?r=users/authority" method="post" >                    <tr>                        <td>角色:</td>                        <td class="input-group input-group-sm">                            <span class="input-group-addon">@</span>                            <?php                            foreach($roleList as $v){;?>                                <input type="checkbox" name="role_id[]" value="<?php echo $v['role_id']  ;?>"<?php if($v['check']=='check'){ ?>checked="checked" <?php } ;?>/><?php echo $v['role_name']  ;?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                            <?php  };?>                        </td>                    </tr>                    <tr>                        <td>                            <input type="hidden" name="user_id" value="<?php echo $user_id ;?>"/>                        </td>                        <td><input type="submit" value="submit"></td>                    </tr>                </form>            </table>        </center>    </div><!-- /.page-content --></div><!-- /.main-content -->
2、角色赋节点

<div class="main-content">    <div class="breadcrumbs" id="breadcrumbs">        <script type="text/javascript">            try{ace.settings.check('breadcrumbs' , 'fixed')}catch(e){}        </script>        <ul class="breadcrumb">            <li>                <i class="icon-home home-icon"></i>                <a href="#">节点授权</a>            </li>            <li class="active">控制台</li>        </ul><!-- .breadcrumb -->        <div class="nav-search" id="nav-search">            <form class="form-search">                        <span class="input-icon">                            <input type="text" placeholder="Search ..." class="nav-search-input" id="nav-search-input" autocomplete="off" />                            <i class="icon-search nav-search-icon"></i>                        </span>            </form>        </div><!-- #nav-search -->    </div>    <div class="page-content">        <div class="page-header">            <h1>                权限管理功能                <small>                    <i class="icon-double-angle-right"></i>                    节点授权                </small>            </h1>        </div>        <!-- /.page-header -->        <!-- 添加HTML -->        <center>            <table>                <form action="?r=role/authority" method="post" >                    <tr>                        <td>节点:</td>                        <td class="input-group input-group-sm">                            <span class="input-group-addon">@</span>                            <?php                            foreach($nodeLists as $v){;?>                                <input type="checkbox" class="node" name="node_id[]" id="<?php echo $v['node_id']  ;?>" parent_id="<?php echo $v['parent_id'] ;?>" value="<?php echo $v['node_id']  ;?>"<?php if($v['check']=='check'){ ?>checked="checked" <?php } ;?>/><?php echo $v['node_title']  ;?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                            <?php  };?>                        </td>                    </tr>                    <tr>                        <td>                            <input type="hidden" name="role_id" value="<?php echo $role_id ;?>"/>                        </td>                        <td><input type="submit" value="submit"></td>                    </tr>                </form>            </table>        </center>    </div><!-- /.page-content --></div><!-- /.main-content --><script src="assets/js/jquery1.8.3.js"></script><script>   $(function(){       //上、下级选中      $(".node").click(          function(){          var _this=$(this).val();          var _parent=$(this).attr("parent_id")              if(this.checked){                  $(".node").each(function(){                      if($(this).attr("parent_id")==_this){                          $(this).prop("checked",true)                      }                      if(_parent==$(this).val()){                          $(this).prop("checked",true)                      }                  })              }else {                  $(".node").each(function () {                      if ($(this).attr("parent_id") == _this) {                          $(this).prop("checked", false)                      }                      if (_parent == $(this).val()) {                          $(this).prop("checked", false)                      }                  })              }          }      )   })</script>