YII2框架中使用RBAC对模块,控制器,方法的权限控制及规则的使用示例


Posted in PHP onMarch 18, 2020

本文实例讲述了YII2框架中使用RBAC对模块,控制器,方法的权限控制及规则的使用。分享给大家供大家参考,具体如下:

在使用YII2中自带的RBAC时,需要先配置config/web.php:

return [
  // ...
  'components' => [
    'authManager' => [
      'class' => 'yii\rbac\DbManager',
    ],
    // ...
  ],
];

如果你需要运行yii migrate来创建表,那么config/console.php也需要同上面一样配置一下。

cmd进入项目目录,运行如下命令:

yii migrate --migrationPath=@yii/rbac/migrations

你会发现在数据库中创建了四张表

auth_assignment 角色与用户的关联表
auth_item 存放角色与权限,通过type字段区分
auth_item_child 存放角色与权限的上下级关系
auth_rule 规则表,用于扩展权限功能

为了演示,我们在控制器下分别写四个方法,分别用来创建权限,创建角色,指派角色,使用规则。

IndexController.php代码如下:

<?php

namespace app\controllers;

use YII;
use app\models\MyUserLogin;
use app\rbac\UserUpdSelfRule;
use app\controllers\BaseController;

class IndexController extends BaseController
{

  //首页
  public function actionIndex()
  {
    $this->renderPartial('index');
  }

  //登陆
  public function actionLogin()
  {
    if (YII::$app->request->isPost) {
      $user = new MyUserLogin();
      $user->load(YII::$app->request->post(), '');

      if ($user->login()) {
        echo '登陆成功';
      } else {
        echo '登陆失败';
      }

    } else {
      return $this->renderPartial('login');
    }
  }

  //为了演示,这里我们添加几条权限
  public function actionPer()
  {
    $auth = YII::$app->authManager;
    //创建用户删除权限
    $per = $auth->createPermission('user/del');
    $per->description = '删除用户';
    $auth->add($per);
    //创建用户更新权限
    $per = $auth->createPermission('user/upd');
    $per->description = '更新用户';
    $auth->add($per);
    //创建用户添加权限
    $per = $auth->createPermission('user/add');
    $per->description = '添加用户';
    $auth->add($per);
    //创建用户查看权限
    $per = $auth->createPermission('user/list');
    $per->description = '查看用户列表';
    $auth->add($per);
  }

  //添加角色
  public function actionRole()
  {
    $auth = YII::$app->authManager;

    //添加管理员角色
    $admin = $auth->createRole('admin');
    $admin->description = '管理员';
    $auth->add($admin);
    //给管理员赋予权限
    $auth->addChild($admin, $auth->getPermission('user/del'));
    $auth->addChild($admin, $auth->getPermission('user/upd'));
    $auth->addChild($admin, $auth->getPermission('user/add'));
    $auth->addChild($admin, $auth->getPermission('user/list'));

    //添加普通员工角色
    $employee = $auth->createRole('employee');
    $employee->description = '普通员工';
    $auth->add($employee);
    $auth->addChild($employee, $auth->getPermission('user/list'));
    $auth->addChild($employee, $auth->getPermission('user/add'));
  }

  //给用户指派角色
  public function actionAssign()
  {
    $auth = YII::$app->authManager;

    //注意这里的2是用户的ID,即你用户表user里的ID
    //也可通过YII::$app->user->id获取
    $auth->assign($auth->getRole('admin'), 1);

    $auth->assign($auth->getRole('employee'), 2);
  }

  //添加规则
  public function actionRule()
  {
    $auth = YII::$app->authManager;
    $rule = new UserUpdSelfRule();
    $auth->add($rule);

    //创建权限,与规则关联
    $per = $auth->createPermission('user/upd/updSelf');
    $per->description = '用户只能修改自已';
    $per->ruleName = $rule->name;
    $auth->add($per);

    //这里,要注意,要把user/upd/updSelf权限设为user/upd的父级
    //要不然,普通员工访问user/upd这个方法会被拦住
    $auth->addChild($per, $auth->getPermission('user/upd'));
    //给普通员工赋予user/upd/updSelf权限,注意我们这里并没有给员工赋予user/upd权限
    $auth->addChild($auth->getRole('employee'), $per);
  }
}

我们在项目目录下创建rbac目录,并创建UserUpdSelfRule.php,来实现用户只能修改自已信息的规则。

<?php

//注意命名空间要跟你的目录对应
namespace app\rbac;

use yii\rbac\Rule;

//必须继承自yii\rbac\Rule
class UserUpdSelfRule extends Rule
{
  public $name = 'userUpdSelf';

  //必须要实现execute方法
  //$user表示用户ID
  //$item规则相关的角色或者权限
  //$params传递过来的参数
  public function execute($user, $item, $params)
  {
    //如果没有设置参数ID,直接返回true
    if (!isset($params['id'])) {
      return true;
    }
    //判断id是否是当前用户ID
    return ($params['id'] == $user) ? true : false;
  }
}

我们访问index/per查看数据表中的变化。

YII2框架中使用RBAC对模块,控制器,方法的权限控制及规则的使用示例

访问index/role结果如下:

YII2框架中使用RBAC对模块,控制器,方法的权限控制及规则的使用示例

访问index/assign结果如下:

YII2框架中使用RBAC对模块,控制器,方法的权限控制及规则的使用示例

访问index/rule结果如下:

YII2框架中使用RBAC对模块,控制器,方法的权限控制及规则的使用示例

为了能够对我们的模块,控制器,方法进行权限控制,我们需要创建一个基类来统一处理,上面的控制器就是继承自基类。

BaseController.php代码如下:

<?php

namespace app\controllers;

use YII;
use yii\web\Controller;

class BaseController extends Controller
{
  //不需要验证的
  protected $noCheckAccess = [
    'index/index',
    'index/per',
    'index/role',
    'index/assign',
    'index/rule',
    'index/login',
  ];

  //不需要登陆的
  protected $noLogin = [
    'index/login',
  ];

  //验证权限
  //注意,不要把获取模块名,控制器名,方法名写到init()函数里,那样是获取不到的
  //这个坑我已经踩了,大家就不用再去踩了
  public function beforeAction($action)
  {
    $mid = !empty($this->module->id) ? $this->module->id : '';
    $cid = !empty($this->id) ? $this->id : '';
    $aid = !empty($action->id) ? $action->id : '';

    //如果模块为basic,我们只验证控制器/方法
    if ($mid == 'basic') {
      $per = "{$cid}/{$aid}";
    } else {
      $per = "{$mid}/{$cid}/{$aid}";
    }

    if (!in_array($per, $this->noLogin)) {
      if (!$this->checkOnline()) {
        $this->redirect('index/login');
      }
    }

    if (!in_array($per, $this->noCheckAccess)) {
      if (!YII::$app->user->can($per)) {
        die('你没有权限');
      }
    }

    return parent::beforeAction($action);
  }

  //检查是否在线
  public function checkOnline()
  {
    return !empty(YII::$app->user->id) ? true : false;
  }
}

为了演示,我们创建一个UserController.php,代码如下:

<?php

namespace app\controllers;

use YII;
use app\controllers\BaseController;

class UserController extends BaseController
{
  public function actionUpd()
  {
    $id = YII::$app->request->get('id', 0);

    echo 'user id : ', YII::$app->user->id, '<br>';

    //先判断用户有没有只能修改自已的权限
    if (YII::$app->user->can('user/upd/updSelf')) {
      //然后再判断修改ID是否与自已的ID一样,在UserUpdSelfRule里进行判断
      if (YII::$app->user->can('user/upd/updSelf', ['id' => $id])) {
        echo '有权修改自已';
      } else {
        echo '不能修改除自已以外的';
      }
    } else {
      echo '修改所有';
    }
  }

  public function actionDel()
  {
    echo 'user id : ', YII::$app->user->id, '<br>';
    echo 'user del';
  }

  public function actionList()
  {
    echo 'user id : ', YII::$app->user->id, '<br>';
    echo 'user list';
  }

  public function actionAdd()
  {
    echo 'user id : ', YII::$app->user->id, '<br>';
    echo 'user add';
  }
}

我的用户表里有两个用户

YII2框架中使用RBAC对模块,控制器,方法的权限控制及规则的使用示例

分别登陆这两个用户,然后让他们访问user/add,user/del,user/list,user/upd,结果如下:

admin用户状态如下:

YII2框架中使用RBAC对模块,控制器,方法的权限控制及规则的使用示例

test用户状态如下:

YII2框架中使用RBAC对模块,控制器,方法的权限控制及规则的使用示例

test之所以能够访问user/upd是因为我们把user/upd/updSelf设为了user/upd的父级,如果没有设置,这里是会被拦住的。

希望本文所述对大家基于Yii框架的PHP程序设计有所帮助。

PHP 相关文章推荐
php smarty的预保留变量总结
Dec 04 PHP
PHP 图片上传实现代码 带详细注释
Apr 29 PHP
php expects parameter 1 to be resource, array given 错误
Mar 23 PHP
flash用php连接数据库的代码
Apr 21 PHP
php调用mysql数据 dbclass类
May 07 PHP
PHP的可变变量名的使用方法分享
Feb 05 PHP
解析PHP多种序列化与反序列化的方法
Jun 06 PHP
PHP中ini_set与ini_get用法实例
Nov 04 PHP
PHP+MySQL实现的简单投票系统实例
Feb 24 PHP
PHP使用Redis长连接的方法详解
Feb 12 PHP
PHP判断函数是否被定义的方法
Jun 21 PHP
layui数据表格自定义每页条数limit设置
Oct 26 PHP
Laravel框架下的Contracts契约详解
Mar 17 #PHP
使用Entrust扩展包在laravel 中实现RBAC的功能
Mar 16 #PHP
PHP代码加密的方法总结
Mar 13 #PHP
YII2框架中behavior行为的理解与使用方法示例
Mar 13 #PHP
YII2框架中actions的作用与使用方法示例
Mar 13 #PHP
PHP正则之正向预查与反向预查讲解与实例
Apr 06 #PHP
TP5框架安全机制实例分析
Apr 05 #PHP
You might like
十天学会php之第二天
2006/10/09 PHP
php 全文搜索和替换的实现代码
2008/07/29 PHP
PHPTree――php快速生成无限级分类
2018/03/30 PHP
JavaScript获得选中文本内容的方法
2008/12/02 Javascript
学习面向对象之面向对象的基本概念:对象和其他基本要素
2010/11/30 Javascript
javascript innerHTML使用分析
2010/12/03 Javascript
JavaScript学习笔记(二) js对象
2011/10/25 Javascript
jquery中选择块并改变属性值的方法
2013/07/31 Javascript
如何学习Javascript入门指导
2013/11/01 Javascript
javascript实现的字符串与十六进制表示字符串相互转换方法
2015/07/17 Javascript
javascript基础知识
2016/06/07 Javascript
原生js仿淘宝网商品放大镜效果
2017/02/28 Javascript
label+input实现按钮开关切换效果的实例
2017/08/16 Javascript
JS实现仿微信支付弹窗功能
2018/06/25 Javascript
JavaScript中十种一步拷贝数组的方法实例详解
2019/04/22 Javascript
微信小程序使用websocket通讯的demo,含前后端代码,亲测可用
2019/05/22 Javascript
JS实现的碰撞检测与周期移动完整示例
2019/09/02 Javascript
vue实现网络图片瀑布流 + 下拉刷新 + 上拉加载更多(步骤详解)
2020/01/14 Javascript
npm ci命令的基本使用方法
2020/09/20 Javascript
Vue看了就会的8个小技巧
2021/01/21 Vue.js
[05:07]DOTA2英雄梦之声_第14期_暗影恶魔
2014/06/20 DOTA
Python获取邮件地址的方法
2015/07/10 Python
python文本数据相似度的度量
2018/03/12 Python
Python 比较文本相似性的方法(difflib,Levenshtein)
2018/10/15 Python
详细介绍pandas的DataFrame的append方法使用
2019/07/31 Python
python读取与处理netcdf数据方式
2020/02/14 Python
Python函数默认参数常见问题及解决方案
2020/03/26 Python
安装python依赖包psycopg2来调用postgresql的操作
2021/01/01 Python
python反扒机制的5种解决方法
2021/02/06 Python
解析HTML5中的新功能本地存储localStorage
2016/03/01 HTML / CSS
Levi’s西班牙官方网站:李维斯,著名的牛仔裤品牌
2020/08/20 全球购物
奥巴马英文演讲稿
2014/05/15 职场文书
护理目标管理责任书
2014/07/25 职场文书
教师四风问题对照检查材料
2014/09/26 职场文书
社区党员群众路线教育实践活动心得体会
2014/11/03 职场文书
2014年公路养护工作总结
2014/12/04 职场文书