基于rbac的ActionFilter

  1. 新建一个 RoleBaseAccessControl ActionFilter,该过滤器会在每个action执行之前,检查用户是否具有权限 lcfirst(Inflector::id2camel($action->id)) . Inflector::id2camel($controller->id) (例如,用户请求 index.php?r=user/add,那么用户需要具有addUser权限),如果没有抛出 ForbiddenHttpException 或跳转到登录页面。

namespace app\modules\base\filters;

use Yii;
use yii\base\Action;
use yii\base\ActionFilter;
use yii\di\Instance;
use yii\web\ForbiddenHttpException;
use yii\web\User;

class RoleBaseAccessControl extends ActionFilter {
    /**
     * @var User|array|string the user object representing the authentication status or the ID of the user application component.
     * Starting from version 2.0.2, this can also be a configuration array for creating the object.
     */
    public $user = 'user';
    /**
     * @var callable a callback that will be called if the access should be denied
     * to the current user. If not set, [[denyAccess()]] will be called.
     *
     * The signature of the callback should be as follows:
     *
     * ```php
     * function ($rule, $action)
     * ```
     *
     * where `$rule` is the rule that denies the user, and `$action` is the current [[Action|action]] object.
     * `$rule` can be `null` if access is denied because none of the rules matched.
     */
    public $denyCallback;

    /**
     * Initializes the [[rules]] array by instantiating rule objects from configurations.
     */
    public function init() {
        parent::init();
        $this->user = Instance::ensure($this->user, User::className());
    }

    /**
     * This method is invoked right before an action is to be executed (after all possible filters.)
     * You may override this method to do last-minute preparation for the action.
     * @param Action $action the action to be executed.
     * @return boolean whether the action should continue to be executed.
     */
    public function beforeAction($action) {
        $user = $this->user;
        $controller = $action->controller;
        $permission = lcfirst(Inflector::id2camel($action->id)) . Inflector::id2camel($controller->id);

        if ($user->can($permission)) {
            return true;
        }

        if ($this->denyCallback !== null) {
            call_user_func($this->denyCallback, null, $action);
        } else {
            $this->denyAccess($user);
        }

        return false;
    }

    /**
     * Denies the access of the user.
     * The default implementation will redirect the user to the login page if he is a guest;
     * if the user is already logged, a 403 HTTP exception will be thrown.
     * @param User $user the current user
     * @throws ForbiddenHttpException if the user is already logged in.
     */
    protected function denyAccess($user) {
        if ($user->getIsGuest()) {
            $user->loginRequired();
        } else {
            throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
        }
    }
}
  1. 在需要实现权限控制的控制其中添加该ActionFilter,例如
public function behaviors() {
    return [
        'rbac' => [
            'class' => \app\modules\base\filters\RoleBaseAccessControl::className(),
        ],
        'verbs' => [
            'class' => VerbFilter::className(),
            'actions' => [
                'delete' => ['POST'],
            ],
        ],
    ];
}

你可能感兴趣的:(Yii2,php)