资讯专栏INFORMATION COLUMN

Yii2的RBAC实现

xiaoxiaozi / 992人阅读

摘要:一的前期准备的权限管理需要知道怎么给用户分配角色,给角色分配权限,以权限来精细化需要的操作,判断是否有权限来操作这一步,达到管理权限的目的。若没有则渲染不显示数据提交更新相应的修改或者增加。

一、RBAC的前期准备

RBAC的权限管理需要知道怎么给用户分配角色,给角色分配权限,以权限来精细化需要的操作,判断是否有权限来操作这一步,达到管理权限的目的。
先展示下要达到的效果 :

左边为三剑客:用户、角色、权限;
下面为测试页面
二、RBAC的数据表
用户表用的是yii2-admin中migration里面的用户表

create table `user`
(
    `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    `username` varchar(32) NOT NULL,
    `auth_key` varchar(32) NOT NULL,
    `password_hash` varchar(256) NOT NULL,
    `password_reset_token` varchar(256),
    `email` varchar(256) NOT NULL,
    `status` integer not null default 1,
    `created_at` integer not null,
    `updated_at` integer not null,
    KEY `email` (`email`)

)ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `role` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL DEFAULT "" COMMENT "角色名称",
  `status` tinyint(1) NOT NULL DEFAULT "1" COMMENT "状态 1:有效 0:无效",
  `updated_time` timestamp NOT NULL DEFAULT "0000-00-00 00:00:00" COMMENT "最后一次更新时间",
  `created_time` timestamp NOT NULL DEFAULT "0000-00-00 00:00:00" COMMENT "插入时间",
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT="角色表";

CREATE TABLE `permission` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(50) NOT NULL DEFAULT "" COMMENT "权限名称",
  `urls` varchar(1000) NOT NULL DEFAULT "" COMMENT "json 数组",
  `status` tinyint(1) NOT NULL DEFAULT "1" COMMENT "状态 1:有效 0:无效",
  `updated_time` timestamp NOT NULL DEFAULT "0000-00-00 00:00:00" COMMENT "最后一次更新时间",
  `created_time` timestamp NOT NULL DEFAULT "0000-00-00 00:00:00" COMMENT "插入时间",
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT="权限详情表";


CREATE TABLE `user_role` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `uid` int(11) NOT NULL DEFAULT "0" COMMENT "用户id",
  `role_id` int(11) NOT NULL DEFAULT "0" COMMENT "角色ID",
  `created_time` timestamp NOT NULL DEFAULT "0000-00-00 00:00:00" COMMENT "插入时间",
  PRIMARY KEY (`id`),
  KEY `uid` (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT="用户角色表";



CREATE TABLE `role_permisson` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `role_id` int(11) NOT NULL DEFAULT "0" COMMENT "角色id",
  `permission_id` int(11) NOT NULL DEFAULT "0" COMMENT "权限id",
  `created_time` timestamp NOT NULL DEFAULT "0000-00-00 00:00:00" COMMENT "插入时间",
  PRIMARY KEY (`id`),
  KEY `role_id` (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT="角色权限表";

三、视图渲染部分。
将准备好的页面放到views层,在models层建立和表相对应的文件
文件结构:
models层:

view层:

四、逻辑部分:
以角色的增加和修改、给角色增加权限为例:
1、RoleController代码:

where([ "status" => 1 ])->orderBy(["id"=>SORT_DESC])->all();
        return $this->render("index",["roles"=>$roles]);
    }
   /*
    *方法讲解:
    *编辑+新增
    *1、如果能获取到角色的id。则从数据库取出数据来渲染。若没有则渲染不显示数据
    *2、提交更新相应的修改或者增加。同样以id来区分
    *3、新增方法简化还可用load()方法
    */
    public function actionEdit(){
        if (Yii::$app->request->isPost){
            //这个request方法是封装的获取参数的方法在后面的BaseController里面可以找到
            $id = $this->request("id",0);
            $name = $this->request("name","");
            $date_now = date("Y-m-d H:i:s");
            //验证参数TODO:

            $role = Role::find()->where([ "id" => $id ])->one();
            if( $role ){//编辑动作
                $role = $role;
            }else{//添加动作
                $role = new Role();
                $role->status = 1;
                $role->created_time = $date_now;
            }
            $role->name = $name;
            $role->updated_time = $date_now;

            $res = $role->save(0);
            if ($res){
                return $this->redirect("/role/index");
            }
        }
        $id = $this->request("id",0);
        $role = [];
        if( $id ){
            $role = Role::find()->where([ "id" => $id ])->one();
        }
        return $this->render("edit",[
            "role" => $role
        ]);

    }
    /*
    *最重要的一步:展示权限和该角色已经拥有的权限
    */
    public function actionSet(){
        if (Yii::$app->request->isPost){
                //实现保存选中权限的逻辑
            $id = $this->request("id",0);
            $permission_ids = $this->request("permission_ids",[]);

            //验证参数TODO:

            //取出所有已分配给指定角色的权限
            $role_permission_list = RolePermission::find()->where([ "role_id" => $id ])->asArray()->all();
            $assign_permission_ids = array_column( $role_permission_list,"permission_id" );
            /**
             * 找出删除的权限
             * 假如已有的权限集合是A,界面传递过得权限集合是B
             * 权限集合A当中的某个权限不在权限集合B当中,就应该删除
             * 使用 array_diff() 计算补集
             */
            $delete_permission_ids = array_diff( $assign_permission_ids,$permission_ids );
            if( $delete_permission_ids ){
                RolePermission::deleteAll([ "role_id" => $id,"permission_id" => $delete_permission_ids ]);
            }

            /**
             * 找出添加的权限
             * 假如已有的权限集合是A,界面传递过得权限集合是B
             * 权限集合B当中的某个权限不在权限集合A当中,就应该添加
             * 使用 array_diff() 计算补集
             */
            $new_permission_ids = array_diff( $permission_ids,$assign_permission_ids );
            if( $new_permission_ids ){
                foreach( $new_permission_ids as $permission_id  ){
                    $role_permission = new RolePermission();
                    $role_permission->role_id = $id;
                    $role_permission->permission_id = $permission_id;
                    $role_permission->created_time = date("Y-m-d H:i:s");
                    $role_permission->save( 0 );
                }
            }
            return $this->redirect("/role/index");
        }
        $id = $this->request("id",0);
        //验证数据TODO:
        $role = Role::find()->where([ "id" => $id ])->one();
        
        //取出所有的权限
        $permissions = Permission::find()->where([ "status" => 1 ])->orderBy( [ "id" => SORT_DESC ])->all();
       
       

        //取出所有已分配的权限
        $role_permission= RolePermission::find()->where([ "role_id" => $id ])->asArray()->all();
        
        $role_permission_ids = array_column( $role_permission,"permission_id" );
        return $this->render("set",[
            "role" => $role,
            "permissions" => $permissions,
            "role_permission_ids" => $role_permission_ids
        ]);

    }
}

2、由于基础的增加改查都会编写。在这里写set模板渲染
set.php在view中的role目录,代码如下:

">
">

给三剑客增加、修改、删除的核心代码已经结束
五、基础控制器的编写:
实现辨别是否有权限访问要访问的页面
BaseController

checkLoginStatus();
        if ( !$login_status && !in_array( $action->uniqueId,$this->allowAllAction )  ) {
            
            $this->redirect( "/site/login" );//返回到登录页面
            
            return false;
        }
  
        // *
        //  * 判断权限的逻辑是
        //  * 取出当前登录用户的所属角色,
        //  * 在通过角色 取出 所属 权限关系
        //  * 在权限表中取出所有的权限链接
        //  * 判断当前访问的链接 是否在 所拥有的权限列表中
         
        //判断当前访问的链接 是否在 所拥有的权限列表中
       
        if( !$this->checkPrivilege( $action->getUniqueId() ) ){
            $this->redirect( "/test/forbidden");

            return false;
        }
        return true;
    }

    //检查是否有访问指定链接的权限
    public function checkPrivilege( $url ){
        //如果是超级管理员 也不需要权限判断,这里可以根据自己需要更改
        if( Yii::$app->user->identity->id == 1 ){
            return true;
        }

        //有一些页面是不需要进行权限判断的
        if( in_array( $url,$this->ignore_url ) ){
            return true;
        }

        return in_array( $url, $this->getRolePrivilege( ) );
    }

    /*
    * 获取某用户的所有权限
    * 取出指定用户的所属角色,
    * 在通过角色 取出 所属 权限关系
    * 在权限表中取出所有的权限链接
    */
    public function getRolePrivilege($uid = 0){
        if( !$uid){
            $uid = Yii::$app->user->identity->id;
        }

        if( !$this->privilege_urls ){
            $role_ids = UserRole::find()->where([ "uid" => $uid ])->select("role_id")->asArray()->column();
            if( $role_ids ){
                //在通过角色 取出 所属 权限关系
                $permission_ids = RolePermission::find()->where([ "role_id" =>  $role_ids ])->select("permission_id")->asArray()->column();
                //在权限表中取出所有的权限链接
                $list = Permission::find()->where([ "id" => $permission_ids ])->all();
                $urls = [];
                if( $list ){
                    foreach( $list as $_item  ){
                        $tmp_urls = @json_decode(  $_item["urls"],true );
                        $urls[] = $tmp_urls;
                    }
                        $this->privilege_urls = array_merge( $this->privilege_urls,$urls );
                }
            }
        }
        return $this->privilege_urls ;
    }


    //验证登录是否有效,返回 true or  false
    protected function checkLoginStatus(){
        if (Yii::$app->user->isGuest){
            return false;
        }       
        return true;
    }
    public  function request($key, $def = false) {
        $result = $def;
        if(isset($key)) {
            $request = Yii::$app->getRequest();
            if($request->isGet) {
                $result = $request->get($key, $def);
            }else if($request->isPost) {
                $result = $request->post($key, $def);
            }
        }
        return $result;
    }
}

整体代码没有准备,如有需要可以留言,准备后会将链接写在这里。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/25601.html

相关文章

  • Yii2 restful接口方式开发,权限控制(yii2-rest-rbac)

    摘要:根据修改,只是方式,这个相当于的版本。适合用于前后端分离项目,方式提供接口,实现对接口的权限控制。 根据yii2-admin(https://github.com/mdmsoft/yi...)修改,yii2-admin只是web方式,这个相当于yii2-admin的rest版本。适合用于前后端分离项目,rest方式提供接口,实现对接口的权限控制。项目地址:https://github....

    whataa 评论0 收藏0
  • yii2搭建完美后台并实现rbac权限控制实例教程

    摘要:利用渲染后台模板后台的模板我们采用利用插播一曲是一个完全响应管理模板。基于框架,易定制模板。适合多种屏幕分辨率,从小型移动设备到大型台式机。内置了多个页面,包括仪表盘邮箱日历锁屏登录及注册错误错误等页面。 作者:白狼 出处:http://www.manks.top/yii2_fra... 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保...

    neu 评论0 收藏0
  • RBAC笔记

    摘要:例如,系统中某个用户辞职了,只需要将系统中该用户的角色授权撤销即可。 Q0.有哪些概念需要知道? 一些概念的具体定义如下 用户(user): 和计算机系统交互的人(在许多设计方案中,单个用户可能拥有多个登录标识(ID),这些标识可能同时处于活跃状态,但身份验证机制可以使多个标识匹配到某个具体的人,即用户对于计算机系统来说具有唯一性) 主体(subject): 一个代表用户行为的计算机...

    ZweiZhao 评论0 收藏0
  • Yii2系列教程五:简单用户权限管理

    摘要:原文来自上一篇文章讲了用户的注册,验证和登录,这一篇文章按照约定来说说之中的用户和权限控制。探寻上面的一些列设置和代码更改,已经实现了一小部分的用户控制登录的用户才能发表。 原文来自: https://jellybool.com/post/programming-with-yii2-user-access-controls 上一篇文章讲了用户的注册,验证和登录,这一篇文章按照...

    livem 评论0 收藏0
  • Yii2-admin插件用法

    摘要:一安装下载安装二配置这里记得用单引号而不是双引号在配置文件中用对整个项目规则限制配置完后取消这个这里是允许访问的三创建数据库上面的命令会在数据库创建表和表。相关表或者执行里的语句四地址栏加上访问即可出现 一、安装 https://github.com/mdmsoft/yii2-admin 下载安装: composer require mdmsoft/yii2-admin 2.x-dev...

    chaos_G 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<