首页 > PHP开发 > Yii2 > yii2权限(RBAC)
2014
12-04

yii2权限(RBAC)

授权

授权是验证用户是否有足够的权限做一些事情的过程。 Yii提供控制它的几种方法。

访问控制基础(Access control basics

Access control basics很简单实现使用[[yii\web\AccessControl]]:

class SiteController extends Controller
{
    public function behaviors()
    {
        return [
            'access' => [
                'class' => \yii\web\AccessControl::className(),
                'only' => ['login', 'logout', 'signup'],
                'rules' => [
                    [
                        'actions' => ['login', 'signup'],
                        'allow' => true,
                        'roles' => ['?'],
                    ],
                    [
                        'actions' => ['logout'],
                        'allow' => true,
                        'roles' => ['@'],
                    ],
                ],
            ],
        ];
    }
    // ...

在上面的代码中,我们要附加的访问控制行为给控制器。因为只有指定的选项,它会被应用到'登录''退出',只有'注册'的行动。一组基本的选择规则[[yii\web\AccessRule]]内容如下:

  • 让所有来宾(尚未验证)的用户访问“登录”和“注册”的行动。
  • 允许通过验证的用户才能访问'注销'的行动。

规则检查一个接一个从顶部到底部。如果规则匹配,动作立即发生。如果没有,下一个规则进行检查。如果没有规则匹配的访问被拒绝。

[[yii\web\AccessRule]] 是相当灵活的,允许另外什么被证明检查IP地址和请求方法(即POSTGET)。如果不是的话,你可以通过匿名函数指定自己的检查:

class SiteController extends Controller
{
    public function behaviors()
    {
        return [
            'access' => [
                'class' => \yii\web\AccessControl::className(),
                'only' => ['special-callback'],
                'rules' => [
                    [
                        'actions' => ['special-callback'],
                        'allow' => true,
                        'matchCallback' => function ($rule, $action) {
                            return date('d-m') === '31-10';
                        }
                    ],

Action

    // ...
    // Match callback called! 此页面可以访问只有每个1031
    public function actionSpecialCallback()
    {
        return $this->render('happy-halloween');
    }

有时你想,当访问被拒绝采取自定义操作。在这种情况下,你可以指定denyCallback

基于角色的访问控制(RBAC

基于角色的访问控制是非常灵活的方式来控制访问是一个完美的匹配的复杂系统中的权限是可以定制的。

使用基于文件的配置的RBAC

为了开始使用它,需要一些额外的步骤。首先,我们需要配置authManager应用程序组件在应用程序配置文件(web.phpmain.php取决于你使用的模板):

'authManager' => [
    'class' => 'app\components\PhpManager',
    'defaultRoles' => ['guest'],
],

经常使用角色存储在同一个数据库表的其它用户数据。在这种情况下,我们可以将它定义通过创建自己的组件app/components/PhpManager.php

<?php
namespace app\components;
 
use Yii;
 
class PhpManager extends \yii\rbac\PhpManager
{
    public function init()
    {
        parent::init();
        if (!Yii::$app->user->isGuest) {
            //我们假设用户的角色是存储在身份
            $this->assign(Yii::$app->user->identity->id, Yii::$app->user->identity->role);
        }
    }
}

然后在创建权限层次结构@app/data/rbac.php:

<?php
use yii\rbac\Item;
 
return [
    //这是你们的管理任务
    'manageThing0' => ['type' => Item::TYPE_OPERATION, 'description' => '...', 'bizRule' => NULL, 'data' => NULL],
    'manageThing1' => ['type' => Item::TYPE_OPERATION, 'description' => '...', 'bizRule' => NULL, 'data' => NULL],
    'manageThing2' => ['type' => Item::TYPE_OPERATION, 'description' => '...', 'bizRule' => NULL, 'data' => NULL],
    'manageThing3' => ['type' => Item::TYPE_OPERATION, 'description' => '...', 'bizRule' => NULL, 'data' => NULL],
 
    //过程中的作用
    'guest' => [
        'type' => Item::TYPE_ROLE,
        'description' => 'Guest',
        'bizRule' => NULL,
        'data' => NULL
    ],
 
    'user' => [
        'type' => Item::TYPE_ROLE,
        'description' => 'User',
        'children' => [
            'guest',
            'manageThing0', //用户可以编辑thing0
        ],
        'bizRule' => 'return !Yii::$app->user->isGuest;',
        'data' => NULL
    ],
 
    'moderator' => [
        'type' => Item::TYPE_ROLE,
        'description' => 'Moderator',
        'children' => [
            'user',         //user能做的他都可以做
            'manageThing1', //用户可以编辑thing1
        ],
        'bizRule' => NULL,
        'data' => NULL
    ],
 
    'admin' => [
        'type' => Item::TYPE_ROLE,
        'description' => 'Admin',
        'children' => [
            'moderator',    // 能做moderator可以做的所有东西
            'manageThing2', // 也可以管理 thing2
        ],
        'bizRule' => NULL,
        'data' => NULL
    ],
 
    'godmode' => [
        'type' => Item::TYPE_ROLE,
        'description' => 'Super admin',
        'children' => [
            'admin',        // admin能做的都可以做
            'manageThing3', // 也可以管理 thing3
        ],
        'bizRule' => NULL,
        'data' => NULL
    ],
 
];

现在,您可以从RBAC在控制器的访问控制配置指定的角色

public function behaviors()
{
    return [
        'access' => [
            'class' => 'yii\web\AccessControl',
            'except' => ['something'],
            'rules' => [
                [
                    'allow' => true,
                    'roles' => ['manageThing1'],
                ],
            ],
        ],
    ];
}

另一种方法是调用[[yii\web\User::checkAccess()]] 在适当情况下:

使用DB为基础的存储RBAC

在数据库中存储的RBAC层次是低效率的浪费性能的,但要灵活得多。这是因为他比较容易创造一个良好的管理界面,所以如果你需要的权限结构是由最终用户管理的,数据库是您的首选。

在开始之前,你需要配置数据库连接的数据库组件,完成之后得到的  schema-*.sql文件为您的数据库,并执行它。

下一步是配置authManager应用程序组件在应用程序配置文件(web.phpmain.php这取决于你使用的模板):

'authManager' => [
    'class' => 'yii\rbac\DbManager',
    'defaultRoles' => ['guest'],
],

TBD

它是如何工作的

TBD:写一下它的工作原理与图片:)

避免过多的RBAC

为了保持权威性的层次结构简单、高效你应该避免创建和使用过多的节点。大多数时候,简单的检查可以用来代替。对于使用RBAC例如这样的代码

public function editArticle($id)
{
  $article = Article::find($id);
  if (!$article) {
    throw new NotFoundHttpException;
  }
  if (!\Yii::$app->user->checkAccess('edit_article', ['article' => $article])) {
    throw new ForbiddenHttpException;
  }
  // ...
}

可以被替换为一个不使用RBAC的简单代码

public function editArticle($id)
{
    $article = Article::find(['id' => $id, 'author_id' => \Yii::$app->user->id]);
    if (!$article) {
      throw new NotFoundHttpException;
    }
    // ...
}

 
本文翻译自:https://github.com/yiisoft/yii2/blob/master/docs/guide/authorization.md

编程技巧