Yii2 RBAC规则反馈/消息

时间:2016-04-01 09:44:37

标签: yii2 rbac yii2-rbac

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

到目前为止,我发现它工作得相当好并且令人满意,但是我缺少一个关键功能:Yii2规则提供"反馈"以与Yii2 Validators类似的方式设置错误消息以解释验证失败的原因。我正在寻找一种方法来提供某种反馈,说明为什么没有授予许可。

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

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

jQuery.when( deferreds )

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

4 个答案:

答案 0 :(得分:1)

基本上我所做的就是添加

Select ID_Client
     , Counter
     , Length, Amount
     , sum(Counter) over (Partition by ID_CLIENT order by ID_Client, Date_from) as Value1
     , Amount - sum(Counter) over (Partition by ID_CLIENT order by ID_Client, Date_From) as Value2
     , Date_from
     , Date_To
  from TableName 
  order by ID_Client, Date_From, Date_To

遵守我的规则。

确保您分离正确的规则,因此您不会在多个字段上获取该消息,而这些字段没有意义。另外,请确保将其添加到“必需”规则中,除非您希望该消息在其他规则时显示..

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

答案 1 :(得分:0)

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

然后,一旦创建它将它附加到您的控制器:

public function behaviors()
{
    return [
        'access' => [
            'class' => AccessControl::className(),
            'ruleConfig' => [
                'class' => 'app\components\AccessRule'
            ],
            'rules' => [
                /* my normal rules */
            ],
        ],
    ];
}

答案 2 :(得分: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);
}

答案 3 :(得分: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());
}