即使从具有 Yii2 行为的 matchCallback 返回 false 时也设置自定义 denyCallback
Setting custom denyCallback even when returning false from matchCallback with Yii2 behaviours
我正在使用 Yii2
并在我的控制器中使用它们的 behaviors。
我正在构建自己的权限系统,由于权限相当复杂,我需要使用 matchCallback.
这是一个例子:
public function behaviors() {
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['view'],
'rules' => [
[
'allow' => true,
'actions' => ['view'],
'matchCallback' => function ($rule, $action) {
return Yii::$app->authManager->can($rule, $action);
}
],
// everything else is denied
],
],
];
}
现在,不幸的是 matchCallback
的工作方式是 returning true
或 false
是否应该 continue 来执行规则,而不是能够 return 是否允许或不允许。
所以如果我 return false
它不应该继续(因此不允许它们)那么我无法自定义 denyCallback
因为它退出执行规则。
我是否可以自定义 denyCallback
,即使我从 matchCallback
return false
- 或者我应该以不同的方式处理我的情况?
您可以将 denyCallback
定义为 AccessControl
的 属性 而不是在 AccessRule
中定义它。如果 allow
在规则检查 returns null 之后,它将被调用。它与 AccessRule
中的 denyCallback
具有相同的签名:
public function behaviors() {
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['view'],
'rules' => [
[
'allow' => true,
'actions' => ['view'],
'matchCallback' => function ($rule, $action) {
return Yii::$app->authManager->can($rule, $action);
}
],
'denyCallback' => function ($rule, $action){...}
// everything else is denied
],
],
];
}
作为另一种选择,您可以扩展 AccessRule
class 并将 allows()
方法覆盖为 return false 而不是 null 当匹配检查失败时,您的规则 denyCallback
将被调用:
class MyAccessRule extends AccessRule
{
public function allows($action, $user, $request)
{
$allows = parent::allows($action, $user, $request);
if ($allows === null) {
return false;
} else {
return $allows;
}
}
}
matchCallback
只判断是否应用规则,如果 matchCallback
returns true 和其他参数匹配(例如roles、verbs 等),调用 allows()
将 return 规则的 allow
参数 true 或 false 在配置中设置。如果 matchCallback
returns false - allow
将是 null 并且规则的 denyCallback 将不会被调用,但如果在配置中设置了 AccessControl denyCallback
,则会被调用。
正如您在评论中提到的,第三个选项是使 allows()
return 回调结果。
class MyAccessRule extends AccessRule
{
public $allowCallback;
public function allows($action, $user, $request)
{
if(!empty($this->allowCallback) {
return call_user_func($this->allowCallback);
}
$allows = parent::allows($action, $user, $request);
if ($allows === null) {
return false;
} else {
return $allows;
}
}
}
嗯...使用 Yii::$app->authManager->checkAccess($uerId,$permissionName,$dataToPassInArray)
非常简单 then.If 你想要当前登录用户的 id,你应该通过 Yii::$app->user->identity
在 first.Properties 获取当前用户的实例登录用户实例取决于您使用的用户模型(例如 yii\web\User
或其他自定义模型)。
我正在使用 Yii2
并在我的控制器中使用它们的 behaviors。
我正在构建自己的权限系统,由于权限相当复杂,我需要使用 matchCallback.
这是一个例子:
public function behaviors() {
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['view'],
'rules' => [
[
'allow' => true,
'actions' => ['view'],
'matchCallback' => function ($rule, $action) {
return Yii::$app->authManager->can($rule, $action);
}
],
// everything else is denied
],
],
];
}
现在,不幸的是 matchCallback
的工作方式是 returning true
或 false
是否应该 continue 来执行规则,而不是能够 return 是否允许或不允许。
所以如果我 return false
它不应该继续(因此不允许它们)那么我无法自定义 denyCallback
因为它退出执行规则。
我是否可以自定义 denyCallback
,即使我从 matchCallback
return false
- 或者我应该以不同的方式处理我的情况?
您可以将 denyCallback
定义为 AccessControl
的 属性 而不是在 AccessRule
中定义它。如果 allow
在规则检查 returns null 之后,它将被调用。它与 AccessRule
中的 denyCallback
具有相同的签名:
public function behaviors() {
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['view'],
'rules' => [
[
'allow' => true,
'actions' => ['view'],
'matchCallback' => function ($rule, $action) {
return Yii::$app->authManager->can($rule, $action);
}
],
'denyCallback' => function ($rule, $action){...}
// everything else is denied
],
],
];
}
作为另一种选择,您可以扩展 AccessRule
class 并将 allows()
方法覆盖为 return false 而不是 null 当匹配检查失败时,您的规则 denyCallback
将被调用:
class MyAccessRule extends AccessRule
{
public function allows($action, $user, $request)
{
$allows = parent::allows($action, $user, $request);
if ($allows === null) {
return false;
} else {
return $allows;
}
}
}
matchCallback
只判断是否应用规则,如果 matchCallback
returns true 和其他参数匹配(例如roles、verbs 等),调用 allows()
将 return 规则的 allow
参数 true 或 false 在配置中设置。如果 matchCallback
returns false - allow
将是 null 并且规则的 denyCallback 将不会被调用,但如果在配置中设置了 AccessControl denyCallback
,则会被调用。
正如您在评论中提到的,第三个选项是使 allows()
return 回调结果。
class MyAccessRule extends AccessRule
{
public $allowCallback;
public function allows($action, $user, $request)
{
if(!empty($this->allowCallback) {
return call_user_func($this->allowCallback);
}
$allows = parent::allows($action, $user, $request);
if ($allows === null) {
return false;
} else {
return $allows;
}
}
}
嗯...使用 Yii::$app->authManager->checkAccess($uerId,$permissionName,$dataToPassInArray)
非常简单 then.If 你想要当前登录用户的 id,你应该通过 Yii::$app->user->identity
在 first.Properties 获取当前用户的实例登录用户实例取决于您使用的用户模型(例如 yii\web\User
或其他自定义模型)。