Closed akireikin closed 8 years ago
Using this class with yii\rbac\DbManager causes unserialize(): Error
can you be more specific about how you use the class and also provide the stacktrace of the error?
return [
// ...
'components' => [
'authManager' => [
'class' => 'yii\rbac\DbManager',
],
// ...
],
];
class AuthorRule extends yii\rbac\Rule
{
private $activeRecordClass;
public function __construct($activeRecordClass, $config = [])
{
$this->activeRecordClass = $activeRecordClass;
parent::__construct($config);
}
public function execute($user, $item, $params)
{
$class = $this->activeRecordClass;
$ar = $class::findOne($params['id']);
if (!$ar) {
throw new yii\web\NotFoundHttpException();
}
return $user === $ar->user_id;
}
}
class AccessFilter extends \yii\base\ActionFilter
{
public function beforeAction($action)
{
if (Yii::app()->user->can($action->getUniqueId(), ['id' => Yii::app()->request->get('id'))) {
return true;
}
throw new yii\web\ForbiddenHttpException();
}
}
class PostController
{
public $allowUnauthorized = ['index'];
public function behaviors()
{
return [
// 401
'auth' => [
'class' => QueryParamAuth::class,
'tokenParam' => 'token',
'except' => $this->allowUnauthorized,
],
// 403
'access' => [
'class' => AccessFilter::class,
'except' => $this->allowUnauthorized,
],
];
}
/*
|---------
| Actions
|---------
|
*/
}
$auth = Yii::$app->authManager;
// add the rule
$rule = new AuthorRule(Post::class);
$auth->add($rule);
// permissions
$createPost = $auth->createPermission('post/create');
$auth->add($createPost);
$updatePost = $auth->createPermission('post/update');
$auth->add($updatePost);
$updateOwnPost = $auth->createPermission('post/update:own');
$updateOwnPost->ruleName = $rule->name;
$auth->add($updateOwnPost);
$auth->addChild($updateOwnPost, $updatePost);
// roles
$author = $auth->createRole('author');
$auth->add($author);
$auth->addChild($author, $createPost);
$auth->addChild($author, $updateOwnPost);
$admin = $auth->createRole('admin');
$auth->add($admin);
$auth->addChild($admin, $updatePost);
$auth->addChild($admin, $author);
// assigning roles to users
$auth->assign($author, 2);
$auth->assign($admin, 1);
RBAC tree saved in DB without any error. The following error occurs when access control is executed.
{
"name": "PHP Notice",
"message": "unserialize(): Error at offset 77 of 81 bytes",
"code": 8,
"type": "yii\\base\\ErrorException",
"file": "/var/www/myapp/api/vendor/yiisoft/yii2/rbac/DbManager.php",
"line": 573,
"stack-trace": [
"#0 /var/www/myapp/api/vendor/yiisoft/yii2/rbac/BaseManager.php(206): yii\\rbac\\DbManager->getRule()",
"#1 /var/www/myapp/api/vendor/yiisoft/yii2/rbac/DbManager.php(192): yii\\rbac\\BaseManager->executeRule()",
"#2 /var/www/myapp/api/vendor/yiisoft/yii2/rbac/DbManager.php(206): yii\\rbac\\DbManager->checkAccessRecursive()",
"#3 /var/www/myapp/api/vendor/yiisoft/yii2/rbac/DbManager.php(126): yii\\rbac\\DbManager->checkAccessRecursive()",
"#4 /var/www/myapp/api/vendor/yiisoft/yii2/web/User.php(661): yii\\rbac\\DbManager->checkAccess()",
"#5 /var/www/myapp/api/core/http/filters/AccessFilter.php(53): yii\\web\\User->can()",
"#6 /var/www/myapp/api/vendor/yiisoft/yii2/base/ActionFilter.php(71): app\\core\\http\\filters\\AccessFilter->beforeAction()",
"#7 /var/www/myapp/api/vendor/yiisoft/yii2/base/Component.php(541): yii\\base\\ActionFilter->beforeFilter()",
"#8 /var/www/myapp/api/vendor/yiisoft/yii2/base/Component.php(541): ::call_user_func:{/var/www/myapp/api/vendor/yiisoft/yii2/base/Component.php:541}()",
"#9 /var/www/myapp/api/vendor/yiisoft/yii2/base/Controller.php(263): yii\\base\\Component->trigger()",
"#10 /var/www/myapp/api/vendor/yiisoft/yii2/web/Controller.php(108): yii\\base\\Controller->beforeAction()",
"#11 /var/www/myapp/api/vendor/yiisoft/yii2/base/Controller.php(149): yii\\web\\Controller->beforeAction()",
"#12 /var/www/myapp/api/vendor/yiisoft/yii2/base/Module.php(455): yii\\base\\Controller->runAction()",
"#13 /var/www/myapp/api/vendor/yiisoft/yii2/web/Application.php(84): yii\\base\\Module->runAction()",
"#14 /var/www/myapp/api/vendor/yiisoft/yii2/base/Application.php(375): yii\\web\\Application->handleRequest()",
"#15 /var/www/myapp/frontend/app/api/index.php(25): yii\\base\\Application->run()",
"#16 {main}"
]
}
Can you get what's stored in DB and post here?
name | data | created_at | updated_at |
---|---|---|---|
author | O:40:"app\modules\permissions\rules\AuthorRule":4:{s:4:"name";s:6:"author";s:53:" | 1449051344 | 1449051344 |
Aha. Seems you have it trimmed. What's type of the data
column?
The type is text
. BTW, I use PostgreSQL.
Then it's not the case and the reason for trimming is elsewhere. PostgreSQL text could hold about 4GB w/o problems.
@akireikin did you solve your problem?
@SilverFire I stopped using private and protected fields in Rule
classes.
@akireikin Did it fix serialization trimming in DB?
I'm closing the issue because @akireikin is inactive and the problem is not verified.
Found, that it's a PHP peculiarity https://github.com/yiisoft/yii2/issues/10823#issuecomment-183631269
Consider the following example.
Using this class with
yii\rbac\DbManager
causesunserialize(): Error
. I made a little bit of research and it seems the error caused by theprivate
field unserialization.From http://php.net/en/serialize.
...
Of course, I can use public field instead, but it looks like treating the symptom, not the cause. Anyway, at least corresponding docs should be improved.