5

这是一个关于 Yii2 中 RBAC 使用的问题。

到目前为止,我发现它工作得相当好和令人满意,但是我缺少一个关键特性:Yii2 规则提供“反馈”的能力,类似于 Yii2 验证器设置错误消息来解释验证失败的原因. 我正在寻找一种方法来提供某种反馈,说明为什么未授予许可。

特别是,can()方法将返回一个布尔类型,这很好,但是在检查权限时,我们不知道为什么用户没有被授予该特定权限。

举一个更实际的例子。假设我们正在尝试确定当前用户是否可以提交评论。我们通常会这样做:

if (Yii::$app->user->can('postComment',['comment'=>$comment])) {
    $comment->post();
} else {
    throw new ForbiddenHttpException('Sorry m8, you cant do this. No idea why tho!');
}

它工作得很好,但如示例中所示,我们真的不知道为什么用户无法发表评论。可能是多种原因,例如因为线程被锁定或因为他们无权在某个类别中发帖或因为他们没有足够高的声誉等。但我们想告诉用户为什么!所以我的问题是,我们如何从 Yii2 的 RBAC 获得反馈?

4

4 回答 4

0

所以基本上我所做的就是添加

'message' => 'Current password cannot be blank.' 

我的规则。

确保您分开正确的规则,这样您就不会在多个字段上收到该消息,因为它没有意义。还要确保将其添加到“必需”规则中,除非您希望该消息显示为另一条规则。

我希望这对你们有帮助,因为我花了太多时间寻找它。

于 2016-04-02T22:17:26.263 回答
0

您可能希望创建自己的 AccessRule 并通过覆盖该类中的当前方法来设置场景中的消息异常。matchRole将是您将覆盖的方法。Yii2 没有这个,所以你必须滚动你自己的 AccessRule 来这样做。

然后一旦它被创建附加到你的控制器:

public function behaviors()
{
    return [
        'access' => [
            'class' => AccessControl::className(),
            'ruleConfig' => [
                'class' => 'app\components\AccessRule'
            ],
            'rules' => [
                /* my normal rules */
            ],
        ],
    ];
}
于 2016-04-01T16:51:28.033 回答
0

从 RBAC 获得反馈的最快方法是将对象作为参数传递。如果检查失败,则将错误文本输入到该对象中。这样就可以得到检测结果为阴性的原因。

假设我们想阻止用户评论他们的帖子。

规则中的验证。此规则与postComment权限相关联:

class PostCommentRule extends yii\rbac\Rule
{
    public $name = 'PostCommentRuleName';

    public function execute($user, $item, $params)
    {
        $allowed = $params['post']->owner_id !== $user;

        if(!$allowed && isset($params['errorObject']))
            $params['errorObject']->errorText = 'Comments to oneself are not allowed.';

        return $allowed;
    }
}

我们检查许可,如果被禁止,我们有一个理由:

$errorObject = new stdClass();

if (Yii::$app->user->can('postComment',['post'=>$post,'errorObject'=>$errorObject])) {
    $comment->post();
} else {
    throw new ForbiddenHttpException($errorObject->errorText);
}
于 2020-04-19T14:49:20.703 回答
0

在您的情况下,我将创建一个基本权限类,它将使用一种简单的方法涵盖特定限制消息的抽象,并将通过您的所有权限进行扩展。

这是抽象的权限蓝图。

abstract class AbstractPermission extends Permission
{
    /**
     * @return string
     */
    abstract public function getRestrictionMessage(): string;
}

创建自定义数据库管理器以检查检索到的权限是否已实现抽象。

class CustomDbManager extends DbManager 
{
    /**
     * @throws \Exception
     * @return AbstractPermission|null
     */
    public function getPermission($name): ?AbstractPermission 
    {
        $permission = parent::getPermission($name);

        if ($permission === null) {
            return null;
        }

        if (!$permission instanceof AbstractPermission) {
            throw new \Exception(
                'Your permission class should be derived from ' . AbstractPermission::class
            );
        }

        return $permission;
    }
}

CustomDbManager在你的配置文件中定义

'components' => [
    'authManager' => [
        'class' => CustomDbManager::class
    ],
    ...
];

以您的PostCommentPermission.

class PostCommentPermission extends AbstractPermission
{
    /**
     * @return string
     */
    public function getRestrictionMessage(): string
    {
        return 'You cannot post comments!';
    }
}

最后通过特定权限检查调用您的经理

$authManager = Yii::$app->getAuthManager();

$postCommentPermission = $authManager->getPermission('postComment');

if (Yii::$app->user->can($postCommentPermission->name, ['comment' => $comment])) {
    $comment->post();
} else {    
    throw new ForbiddenHttpException($postCommentPermission->getRestrictionMessage());
}
于 2020-04-20T07:26:23.690 回答