即使从matchCallback使用Yii2行为返回false,也可以设置自定义denyCallback

Bre*_*ett 6 php permissions yii user-permissions yii2

我正在我的控制器中使用Yii2和利用他们的行为.

我正在构建自己的权限系统,因为权限相当复杂,我需要使用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
            ],
        ],
    ];
}   
Run Code Online (Sandbox Code Playgroud)

现在,不幸的是一路matchCallback的作品是通过返回truefalse对是否应该继续执行该规则,而不是允许他们还是不能够返回true或false.

因此,如果我返回false它不应该继续(因此不允许它们),那么我无法自定义denyCallback它退出执行规则.

无论如何我可以自定义denyCallback即使我falsematchCallback- 或者我应该以不同的方式处理我的情况吗?

Ton*_*ony 6

您可以将其定义denyCallback为属性AccessControl而不是定义它AccessRule.如果allow在规则检查后返回null,它将被调用.它具有相同的签名denyCallbackAccessRule:

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
            ],
        ],
    ];
}  
Run Code Online (Sandbox Code Playgroud)

作为另一个选项,您可以扩展AccessRuleclass和override allows()方法,以在匹配检查失败时返回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;
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

matchCallback仅确定是否应用规则,如果matchCallback返回true且其他参数匹配(例如角色,动词等),则调用allows()将在配置中设置时返回规则的allow参数truefalse.如果matchCallback返回false - allow将为null并且不会调用rule的denyCallback,但如果在配置中设置了AccessControl, denyCallback则将调用AccessControl.

正如您在评论中提到的,第三个选项是allows()返回回调结果.

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;
        }

    }
}
Run Code Online (Sandbox Code Playgroud)