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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/woshihaiyong168/article/details/53115317

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控制器

<?php
namespace 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;
    }
}
用户控制器

<?php
namespace 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]);
        }
    }
}
角色控制器

<?php
namespace 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;
    }
}


节点控制器

<?php
namespace 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>



展开阅读全文

没有更多推荐了,返回首页