我使用访问控制过滤器进行访问管理,但无法完成任务 - 例如,如何让项目经理更新项目并禁止其他人?我通过matchCallback尝试了它,但在这种情况下,所有项目经理都可以更新任何项目,因为返回了TRUE。
类似更常用的规则 - 如何允许用户使用ACF更新/删除作者的帖子?
'access' => [
'class' => AccessControl::className(),
'only' => ['index', 'view', 'create', 'update', 'delete'],
'rules' => [
[
'actions' => ['update'],
'allow' => true,
'roles' => ['@'],
'matchCallback' => function ($rule, $action) {
return Yii::$app->user->identity->getProjectParticipants()
->one()->isManager(Yii::$app->user->identity->id);
}
],
],
],
答案 0 :(得分:4)
它可以实现如下:
use Yii;
use yii\web\Controller;
use yii\filters\AccessControl;
class MyController extends Controller
{
...
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['update', 'delete'],
'rules' => [
[
'actions' => ['update', 'delete'],
'allow' => true,
'roles' => ['@'],
'matchCallback' => function ($rule, $action) {
if (Yii::$app->user->can('admin') || $this->isUserAuthor()) {
return true;
}
return false;
}
],
],
],
];
}
protected function findModel($id)
{
if (($model = MyModel::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
protected function isUserAuthor()
{
return $this->findModel(Yii::$app->request->get('id'))->author->id == Yii::$app->user->id;
}
...
}
答案 1 :(得分:3)
使用自定义AccessRule
解决了这个问题。人们必须填写代码来检查用户是否是项目的作者。
namespace app\filters;
class AuthorAccessRule extends \yii\filters\AccessRule
{
public $allow = true; // Allow access if this rule matches
public $roles = ['@']; // Ensure user is logged in.
public function allows($action, $user, $request)
{
$parentRes = parent::allows($action, $user, $request);
// $parentRes can be `null`, `false` or `true`.
// True means the parent rule matched and allows access.
if ($parentRes !== true) {
return $parentRes;
}
return ($this->getProjectAuthorId($request) == $user->id);
}
private function getProjectAuthorId($request)
{
// Fill in code to receive the right project.
// assuming the project id is given à la `project/update?id=1`
$projectId = $request->get('id');
$project = \app\models\Project::findOne($projectId);
return isset($project) ? $project->author_id : null;
}
}
可以通过在行为中包含此规则来使用该规则:
'authorAccess' => [
'class' => AccessControl::className(),
'only' => ['update'],
'rules' => ['actions' => ['update']],
'ruleConfig' => ['class' => '\app\filters\AuthorAccessRule'],
],
答案 2 :(得分:1)
以下是我如何使用ACF和RBAC的组合。如果我错了或者有更好的方法,请纠正我。它基于Basic模板。
用户角色存储在“用户”表的“角色”列中。在此示例中使用另一个表“country”。假设您已使用Gii生成模型和控制器。
自定义PhpManager以使用数据库表“user”中的角色。
class PhpManager extends \yii\rbac\PhpManager
{
public function init()
{
parent::init();
}
public function getAssignments($userId)
{
if (!Yii::$app->user->isGuest) {
$assignment = new Assignment();
$assignment->userId = $userId;
# Assume the role is stored in User table "role" column
$assignment->roleName = Yii::$app->user->identity->role;
return [$assignment->roleName => $assignment];
}
}
}
3.将authManager添加到web.app和console.app控制台文件。
'authManager' => [
'class' => 'app\components\PhpManager',
'defaultRoles' => ['user', 'manager', 'admin', 'master'],
],
# Reference
# http://programming.peixoto.cf/2015/01/14/yii2-role-based-access-control-and-context-access-rule/#$$nmvkr0&&0SUmhOPVEeSW9grIhAgzZg$$
class ContextAccessRule extends AccessRule
{
public $modelClass;
public $primaryKey;
protected function matchRole($user)
{
if (parent::matchRole($user))
return true;
$model = $this->findModel();
foreach ($this->roles as $role) {
# Call the CheckAccess() function which process rules
if ($user->can($role, ['model' => $model])) {
return true;
}
}
return false;
}
protected function findModel()
{
if (!isset($this->modelClass))
throw new InvalidConfigException(Yii::t('app', 'the "modelClass" must be set for "{class}".', ['class' => __CLASS__]));
$primaryKey = $this->getPrimaryKey();
# Get the request params
$queryParams = \Yii::$app->getRequest()->getQueryParams();
# Load the model
$model = call_user_func([$this->modelClass, 'findOne'], $queryParams[join(',', $primaryKey)]);
if ($model !== null) {
return $model;
} else {
throw new NotFoundHttpException(Yii::t('app', 'The requested page does not exists.'));
}
}
# Get the primary key of the model
protected function getPrimaryKey()
{
if (!isset($this->primaryKey)) {
return call_user_func([$this->modelClass, 'primaryKey']);
} else {
return $this->primaryKey;
}
}
class RbacController extends Controller
{
public function actionInit()
{
$auth = Yii::$app->authManager;
$auth->removeAll();
### CREATE & ADD ROLES
$user = $auth->createRole('user');
$node = $auth->createRole('node');
$manager = $auth->createRole('manager');
$admin = $auth->createRole('admin');
$master = $auth->createRole('master');
$auth->add($user);
$auth->add($node);
$auth->add($manager);
$auth->add($admin);
$auth->add($master);
$auth->addChild($manager, $user);
$auth->addChild($manager, $node);
$auth->addChild($admin, $manager);
$auth->addChild($master, $admin);
### ADD RULES
$ownerRule = new \app\components\OwnerRule();
$auth->add($ownerRule);
### CREATE PERMISSIONS ###
$pUpdateOwn = $auth->createPermission('updateOwn');
$pUpdateOwn->description = 'update own';
$pUpdateOwn->ruleName = $ownerRule->name;
$auth->add($pUpdateOwn);
$auth->addChild($pUpdateOwn, $pUpdate);
$pDeleteOwn = $auth->createPermission('deleteOwn');
$pDeleteOwn->description = 'delete own';
$pDeleteOwn->ruleName = $ownerRule->name;
$auth->add($pDeleteOwn);
$auth->addChild($pDeleteOwn, $pDelete);
### ASSIGN PERMISSION TO ROLES
$auth->addChild($user, $pUpdateOwn);
$auth->addChild($user, $pDeleteOwn);
$auth->addChild($manager, $pUpdateOwn);
$auth->addChild($manager, $pDeleteOwn);
}
}
从控制台导航到项目根目录。运行./yii rbac/init
(对于mac)将3个文件生成到rbac文件夹中。
在CountryController.php中,覆盖以下函数以添加“访问”行为。
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['verbs'] = [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['post'],
],
];
['access'] = [
'class' => AccessControl::className(),
// 'only' => ['view', 'index', 'create', 'update', 'delete'],
'rules' => [
[
'actions' => ['view', 'index'],
'allow' => true,
'roles' => ['?', '@'],
],
[
'actions' => ['create'],
'allow' => true,
// Allow users, manager and admins to create
'roles' => ['user'],
],
[
'class' => 'app\components\ContextAccessRule',
'modelClass' => 'app\models\Country',
'actions' => ['update'],
'allow' => true,
# allow owner and manager to udpate
'roles' => ['updateOwn', 'manager']
],
[
'class' => 'app\components\ContextAccessRule',
'modelClass' => 'app\models\Country',
'actions' => ['delete'],
'allow' => true,
# allow owner and manager to delete
'roles' => ['deleteOwn', 'manager'],
],
],
# if user not login, and not allowed for current action, return following exception
'denyCallback' => function ($rule, $action) {
throw new UnauthorizedHttpException('You are not authorized.');
},
];
return $behaviors;
}