【问题标题】:Yii RBAC make Users update profile by himselfYii RBAC 让用户自己更新个人资料
【发布时间】:2013-04-07 09:13:21
【问题描述】:

我正在尝试使用mongodbauthmanager 来执行此操作。我在Usage 部分一步一步地进行操作,但最后我收到PHP 警告:非法偏移类型。在克隆到 SO 之前,我已经在 Yii Extension 发布了这个问题:

请告诉我有什么问题?

1// 配置

 'authManager'=>array(
    'class'         =>'CMongoDbAuthManager',
    'showErrors'    => true,
  ),

2//在db中创建认证项

$auth = new CMongoDbAuthManager();

$bizRule = 'return Yii::app()->user->id==$params["User"]->_id;';
$auth->createTask('updateSelf', 'update own information', $bizRule);
//I had tried with $auth->createOperation() but they has the same error
$role = $auth->createRole('user');
$role->addChild('updateSelf');

$auth->save();

这是 db 中的结果 result in db http://i.minus.com/iIpXoBlDxaEfo.png

**3// 检查控制器中的访问权限** - 更新代码和错误

public function actionUpdate($id)
    {
        $model=$this->loadModel($id);
        $params = array('User'=>$model);
        if (!Yii::app()->user->checkAccess('updateSelf', Yii::app()->user->id,$params) )
        {
            throw new CHttpException(403, 'You are not authorized to perform this action');
        }
//another statement ...
}

4// 出现错误:

致命错误:无法将 MongoId 类型的对象用作 F:\Data\03 中的数组。 Lab\www\yii\framework\web\auth\CAuthManager.php(150) : eval()'d 代码在第 1 行

已解决的问题

根据@Willem Renzema 的回答,我解决了我的问题。现在,我在这里更新,希望对遇到此错误的人有用。

0//首先,用defaultRoles配置authManager

   'authManager'=>array(
        'class'=>'CMongoDbAuthManager',
        'showErrors' => true,
        'defaultRoles'=> array('user'),//important, this line help we don't need assign role for every user manually
    ),

1// 修复 UserIdentity 类中的保存 id

class UserIdentity extends CUserIdentity
{
    private $_id;
    //...
    public function authenticate()
    {
         //...
         $this->_id = (string)$user->_id;//force $this save _id by string, not MongoId object
         //...
    }
    //...
}

2// 修复授权项目中的 $bizrule ($bizrule 将由eval() 在checkAccess 中运行)

//use _id as string, not MongoId object
$bizRule = 'return Yii::app()->user->id==(string)$params["User"]->_id;';

3//和用户检查访问权限

public function actionUpdate($id){
        /**
         * @var User $model
         */
        $model=$this->loadModel($id);
        $params = array('User'=>$model);
        if (!Yii::app()->user->checkAccess('updateSelf', $params) )
        {
            throw new CHttpException(403, 'You are not authorized to perform this action');
        }
        //...
}

4// 完成,现在我们可以使用 checkAccess :D

【问题讨论】:

  • 看checkAccess的签名,特别是第二个参数。
  • 是的,我输入 Yii::app()->user->id 并获取 Fatal error: Cannot use object of type MongoId as array in \www\yii\framework\web\auth\CAuthManager.php(150) : eval()'d code on line 1。
  • 那么您更新后的代码是什么样的?从错误消息看来,您似乎也更改了$params...
  • 我改一行:Yii::app()->user->checkAccess('updateSelf', Yii::app()->user->id, $params)
  • 抱歉,我不明白为什么会发生这个问题。它在您的bizRule 的eval 期间失败了,所以也许您可以在其中执行var_dump($params) 或类似的操作。 (使用最新的代码和错误更新您的帖子,以便其他人可以看到状态。)

标签: mongodb yii authorization yii-extensions rbac


【解决方案1】:

首先,您最初使用 checkAccess 是正确的。使用 Yii::app()->user->checkAccess() 您正在使用以下定义:

http://www.yiiframework.com/doc/api/1.1/CWebUser#checkAccess-detail

现在,CWebUser 的 checkAccess 实现调用 CPHPAuthManager 的实现,这是您遇到非法偏移类型问题的地方。

http://www.yiiframework.com/doc/api/1.1/CPhpAuthManager#checkAccess-detail

Illegal offset type 表示您正在尝试通过指定其键(也称为:偏移)来访问数组元素,该值不能用作键。这可能是另一个数组、一个对象、null 或其他东西。

您在扩展页面上发布的堆栈跟踪显示以下行给出了问题:

if(isset($this->_assignments[$userId][$itemName]))

所以对于非法偏移我们有两种可能:$userId 和$itemName。

既然$itemName显然是一个字符串,那么问题肯定出在$userId上。

(作为旁注,您的堆栈跟踪揭示了此错误的周围代码这一事实也表明,至少对于CPHPAuthManager,您使用的是 1.1.11 之前的 Yii 版本。观察这些行https://github.com/yiisoft/yii/blob/1.1.11/framework/web/auth/CPhpAuthManager.php 中的 73 和 74 个不存在于您的文件代码中。)

此时我已经猜到问题是指定用户没有登录,所以Yii::app()->user->id 正在返回null。但是,将Yii::app()->user->id 作为checkAccess 的第二个参数时遇到的新错误揭示了其他问题。

因为第二个参数实际上应该是出现在bizRule 中的$params 数组。根据错误信息,这意味着Yii::app()->user->id 正在返回一个mondoId 类型的对象。

我对这种类型的物体不熟悉,所以查了一下:

http://php.net/manual/en/class.mongoid.php

长话短说,您需要强制 Yii::app()->user->id 返回与此 mondoId 对象等效的字符串值。这可能设置在 components 文件夹中的 UserIdentity 类中。要将其强制为字符串,只需放置 (string) 即可强制进行类型转换。

例子:

$this->_id = (string)$User->_id;

您的确切代码会有所不同,具体取决于您的 UserIdentity 类中的内容。

然后,将你的checkAccess恢复成你之前的签名,它应该消除你最初遇到的Illegal offset error。

但是请注意,我没有使用此扩展,在执行以下操作时应该可以解决此问题,如果扩展依赖于 Yii::app()->user->id 是 mondoId 对象而不是字符串。

【讨论】:

  • 非常感谢!总结一下,checkAccess需要$userId是一个字符串,我这里放的是对象(MongoId)。我已经完成了这个任务。
猜你喜欢
  • 2015-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-13
  • 1970-01-01
  • 1970-01-01
  • 2012-08-01
  • 1970-01-01
相关资源
最近更新 更多