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 MYSQL 数据备份类
Jun 19 PHP
spl_autoload_register与autoload的区别详解
Jun 03 PHP
什么情况下可以不写PHP的闭合标签“?&gt;”
Aug 28 PHP
thinkPHP中分页用法实例分析
Dec 26 PHP
phplist及phpmailer(组合使用)通过gmail发送邮件的配置方法
Mar 30 PHP
PHP抓取及分析网页的方法详解
Apr 26 PHP
深入分析PHP优化及注意事项
Jul 04 PHP
laravel学习教程之存取器
Jul 30 PHP
PHP聚合式迭代器接口IteratorAggregate用法分析
Dec 28 PHP
php实现websocket实时消息推送
Mar 30 PHP
PHP mongodb操作类定义与用法示例【适合mongodb2.x和mongodb3.x】
Jun 16 PHP
laravel-admin自动生成模块,及相关基础配置方法
Oct 08 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项目开发中最常用的自定义函数整理
2010/12/02 PHP
gd库图片下载类实现下载网页所有图片的php代码
2012/08/20 PHP
解析php如何将日志写进syslog
2013/06/28 PHP
PHP get_html_translation_table()函数用法讲解
2019/02/16 PHP
Js+Dhtml:WEB程序员简易开发工具包(预先体验版)
2006/11/07 Javascript
jquery 上下滚动广告
2009/06/17 Javascript
iframe的onreadystatechange事件在firefox下的使用
2014/04/16 Javascript
判断日期是否能跨月查询的js代码
2014/07/25 Javascript
jquery仿百度经验滑动切换浏览效果
2015/04/14 Javascript
js判断文件格式及大小的简单实例(必看)
2016/10/11 Javascript
浅析javaScript中的浅拷贝和深拷贝
2017/02/15 Javascript
通过Nodejs搭建网站简单实现注册登录流程
2019/06/14 NodeJs
JavaScript面向对象中接口实现方法详解
2019/07/24 Javascript
vue element upload组件 file-list的动态绑定实现
2019/10/11 Javascript
vue遍历生成的输入框 绑定及修改值示例
2019/10/30 Javascript
VUE 直接通过JS 修改html对象的值导致没有更新到数据中解决方法分析
2019/12/02 Javascript
vue quill editor 使用富文本添加上传音频功能
2020/01/14 Javascript
jQuery 常用特效实例小结【显示与隐藏、淡入淡出、滑动、动画等】
2020/05/19 jQuery
vue移动端下拉刷新和上滑加载
2020/10/27 Javascript
浅析python 中__name__ = '__main__' 的作用
2014/07/05 Python
用Python实现一个简单的多线程TCP服务器的教程
2015/05/05 Python
Django的数据模型访问多对多键值的方法
2015/07/21 Python
Python3 模块、包调用&amp;路径详解
2017/10/25 Python
django celery redis使用具体实践
2019/04/08 Python
使用Filter过滤python中的日志输出的实现方法
2019/07/17 Python
Python交互式图形编程的实现
2019/07/25 Python
TensorFlow实现模型断点训练,checkpoint模型载入方式
2020/05/26 Python
python实现猜数游戏(保存游戏记录)
2020/06/22 Python
HTML5新增加的功能详解
2016/09/05 HTML / CSS
施华洛世奇德国官网:SWAROVSKI德国
2017/02/01 全球购物
What is the purpose of Void class? Void类的作用是什么?
2016/10/31 面试题
党建示范点实施方案
2014/03/12 职场文书
歌颂祖国的演讲稿
2014/05/04 职场文书
群众路线教育实践活动方案
2014/10/31 职场文书
篮球赛新闻稿
2015/07/17 职场文书
Python中非常使用的6种基本变量的操作与技巧
2022/03/22 Python