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入门学习笔记之一
Oct 12 PHP
深入理解require与require_once与include以及include_once的区别
Jun 05 PHP
php读取csv文件后,uft8 bom导致在页面上显示出现问题的解决方法
Aug 10 PHP
php读取mysql的简单实例
Jan 15 PHP
实现PHP多线程异步请求的3种方法
Jan 17 PHP
dedecms集成财付通支付接口
Dec 28 PHP
PHP中使用substr()截取字符串出现中文乱码问题该怎么办
Oct 21 PHP
详解PHP匿名函数与注意事项
Mar 29 PHP
php接口技术实例详解
Dec 07 PHP
PHP工厂模式的日常使用
Mar 20 PHP
laravel框架中控制器的创建和使用方法分析
Nov 23 PHP
设定php简写功能的方法
Nov 28 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通过修改header强制图片下载的方法
2015/03/24 PHP
学习php设计模式 php实现合成模式(composite)
2015/12/08 PHP
PHP对象、模式与实践之高级特性分析
2016/12/08 PHP
浅谈thinkphp5 instance 的简单实现
2017/07/30 PHP
PHP实现git部署的方法教程
2017/12/19 PHP
javascript下判断一个对象是否具有指定名称的属性的的代码
2010/01/11 Javascript
js 小贴士一星期合集
2010/04/07 Javascript
JS数学函数Exp使用说明
2012/08/09 Javascript
jquery插件制作 提示框插件实现代码
2012/08/17 Javascript
jquery实现微博文字输入框 输入时显示输入字数 效果实现
2013/07/12 Javascript
jQuery的选择器中的通配符使用介绍
2014/03/20 Javascript
JQuery Dialog对话框 不能通过Esc关闭的原因分析及解决办法
2017/01/18 Javascript
AngularJS日程表案例详解
2017/08/15 Javascript
你可能不知道的前端算法之文字避让(inMap)
2018/01/12 Javascript
对mac下nodejs 更新到最新版本的最新方法(推荐)
2018/05/17 NodeJs
vue+axios实现文件下载及vue中使用axios的实例
2018/09/21 Javascript
Fundebug支持监控微信小程序HTTP请求错误的方法
2019/02/21 Javascript
vue实现循环滚动列表
2020/06/30 Javascript
纯js+css实现在线时钟
2020/08/18 Javascript
JS+JQuery实现无缝连接轮播图
2020/12/30 jQuery
[36:02]DOTA2上海特级锦标赛D组小组赛#2 Liquid VS VP第一局
2016/02/28 DOTA
pip 错误unused-command-line-argument-hard-error-in-future解决办法
2014/06/01 Python
python爬虫入门教程--快速理解HTTP协议(一)
2017/05/25 Python
Python实现的选择排序算法示例
2017/11/29 Python
Python使用re模块正则提取字符串中括号内的内容示例
2018/06/01 Python
Centos部署django服务nginx+uwsgi的方法
2019/01/02 Python
python实现的按要求生成手机号功能示例
2019/10/08 Python
NumPy中的维度Axis详解
2019/11/26 Python
Python列表操作方法详解
2020/02/09 Python
Django自定义列表 models字段显示方式
2020/04/03 Python
HTML5之SVG 2D入门13—svg对决canvas及长处和适用场景分析
2013/01/30 HTML / CSS
网站编辑求职信
2013/10/17 职场文书
生日邀请函范文
2014/01/13 职场文书
社区党员先进事迹
2014/01/22 职场文书
模具毕业生推荐信
2014/02/15 职场文书
大学优秀学生主要事迹材料
2015/11/04 职场文书