- 新建一个
RoleBaseAccessControl
ActionFilter
,该过滤器会在每个action
执行之前,检查用户是否具有权限lcfirst(Inflector::id2camel($action->id)) . Inflector::id2camel($controller->id)
(例如,用户请求 index.php?r=user/add,那么用户需要具有addUser
权限),如果没有抛出ForbiddenHttpException
或跳转到登录页面。
<?php
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.'));
}
}
}
- 在需要实现权限控制的控制其中添加该
ActionFilter
,例如
public function behaviors() {
return [
'rbac' => [
'class' => \app\modules\base\filters\RoleBaseAccessControl::className(),
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}