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查看数据表中的变化。

访问index/role结果如下:

访问index/assign结果如下:

访问index/rule结果如下:

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

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 : ','<br>';
        echo 'user del';
    }

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

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

我的用户表里有两个用户

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

admin用户状态如下:

test用户状态如下:

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


1、将Yii2.0advanced版中应用主体frontend或backend应用复制为api应用2、在应用主体api目录的controller新建SiteController.php:namespaceapi\controllers;useYii;useyii\rest\ActiveController;/*SiteController测试控制器*/classSiteControllerextendsActiveCon
Yii2restfulAPI文档一、配置模块:1.Config/main.php:  2.创建模块目录:  3.Module.php:  二、路由配置:  三、控制器:  四、Models:   五、测试:GET:  POST:  PUT:      DELETE:  
Yii在framework/i18n/data/%lang%.php文件中有很多翻译.这是例如germantranslations我想在我的Yii项目中使用Fullcalendar.要翻译此日历,我必须为当前语言提供一个monthNames/dayNames数组.FullcalendarmonthNamesDocumentationYii生成数组的最佳方法是什么:['January'
在Yii2中,官方的页面多语言解决方案有两个:方案1,使用Yii::t()函数,在页面中需要输出文字的地方,使用类似如下代码:<?=Yii::t(‘views/login’,‘hello’)?>这样做的后果是页面上大量充斥着类似的代码,导致页面可读性很差,而且对于同一个页面来说,Yii::t()函数的第一个参数基本上都是
Yii2.0对数据库查询的一些简单的操作123456789101112131415161718192021222324252627282930313233343536373839User::findOne($id);   //此方法返回 主键 id=1  的一条数据(举个例子);  User::find()->where(['name' =
数据查询User::find()->all();此方法返回所有数据;User::findOne($id);此方法返回主键id=1的一条数据(举个例子);User::find()->where(['name'=>'小伙儿'])->one();此方法返回['name'=>'小伙儿']的一条数据;User::find()->where(['n
最近打算提升自己的解决问题能力,于是打算从学习其他框架下手,让我们先去了解yii框架是如何运作的吧!https://www.yiichina.com/访问yii中文网站  让我们先把框架下载下来点击下载框架 科普一下:目前yii框架有三个版本yii1.0、yii1.1、yii2.0貌似即将推出3.0 这里我们
如何在Yii2中检查模型属性的类型(列类型)?ThisoldYiiForumanswer给了我一个结论,在Yii1中我可以使用类似的东西:$model->getMetaData()->columns['attribute-name']->type;但我没有成功将此解决方案移植到Yii2.有人可以帮忙吗?解决方法:您可以使用:$model->getTableSchema()
defined('YII_DEBUG')ordefine('YII_DEBUG',true);defined('YII_ENV')ordefine('YII_ENV','dev');require(__DIR__.'/../vendor/autoload.php');//注册类加载器require(__DIR__.'/../vendor/yii
在NGINX中配置:location/{   if(!-e$request_filename){    rewrite^/(.*)/index.phplast;}这样,当NGINX找不到文件的时候,就会将URL重写为index.php。对于URL中只有域名的情况,因为不存在对应的文件,所以会匹配到。再配置:location~\.php${  include
Yii2.0封装的类足够强大,Mailer的使用方法做一个总结:1、先在main-local.php中做好配置:return[//....'components'=>['mailer'=>['class'=>'yii\swiftmailer\Mailer',],],];详细如下:return[//....'components'=>[
每当我尝试登录我的Yii应用程序时,它都会显示错误CDbConnectionfailedtoopentheDBconnection:couldnotfinddriver.我google了很多个小时,从许多博客我知道我需要pdo_mysql,但已经安装了.在php.ini中我也对这些行做了评论;extension=php_pdo_mysql.dll;extension
我有一个模型Aziende,它与称为Annunci的花药模型相关(1:N),如下所示:'annunci'=>array(self::HAS_MANY,'Annunci','azienda_id'),我想算一下有多少记录确实有这种关系,在mySql中我会做:SELECTcount(*)FROM`aziende`aJOINannuncianONan.azienda_id=a.id我怎么能
我们有一个项目,为孟加拉国最大的服装行业之一建立一个ERP系统.他们有大约20,000名员工,其中约10%的员工每个月都会离职.我们是一家拥有5名PHP开发人员的小公司,对这么大的项目没有多少经验.我们之前使用Codeigniter/ZendFramework和MySQL数据库开发了不同的中小规模项目.对于
我在Yii中有一些表单,使用以下内容以下拉形式从相关表中获取数据列表:dropDownList(CHtml::listData(Company::model()->findAll(array('order'=>'companyASC'))));这是有效的,但这意味着对于每个下拉列表(其中很多)我将这个数组(‘order’=>’公司ASC’放在每一个中.这是最
本文采用Yii文档,经过自己的修改,让读者更容易理解预定义完整列表: boolean : CBooleanValidator 的别名,确保属性的值是CBooleanValidator::trueValue 或CBooleanValidator::falseValue .captcha : CCaptchaValidator 的别名,确保了特性的值等于 CAPTCHA 显示出来
前面已经安装好了yii框架,现在我们来建立第一个Yii应用1、进入您网站更目录2、执行命令:YiiRoot/framework/yiicwebapptestdrive说明:这里的YiiRoot为您Yii框架的安装目录。3、输入以上命令后,会出现一个提示信息:PHPWarning:PHPStartup:Unabletol
一、ThinkPHPThinkPHP(FCS)是一个轻量级的中型框架,是从Java的Struts结构移植过来的中文PHP开发框架。它使用面向对象的开发结构和MVC模式,并且模拟实现了Struts的标签库,各方面都比较人性化,熟悉J2EE的开发人员相对比较容易上手,适合php框架初学者。ThinkPHP的宗旨是简化开发、提
我必须实现标题中提到的验证,即需要两个字段之一(电子邮件,电话).我在我的模型中这样做:[['email'],'either',['other'=>['phone']]],这是方法:publicfunctioneither($attribute_name,$params){$field1=$this->getAttributeLabel($attribute_nam
我试图得到(StatusCode)响应RESTapi,而它只返回字段名称和错误消息,如下所示[{"field":"Email","message":"Email\"ali@ali.ali\"hasalreadybeentaken."}]我添加了回复'response'=>['class'=>'