yiisoft / yii2

Yii 2: The Fast, Secure and Professional PHP Framework
http://www.yiiframework.com
BSD 3-Clause "New" or "Revised" License
14.23k stars 6.91k forks source link

yii\rbac\DbManager serialization issue #18681

Open donny26utama opened 3 years ago

donny26utama commented 3 years ago

I got this error image

for emergency I solve this with extends yii\rbac\DbManager and overwrite function:

public function getRule($name)
    {
        if ($this->rules !== null) {
            return isset($this->rules[$name]) ? $this->rules[$name] : null;
        }

        $row = (new Query())->select(['data'])
            ->from($this->ruleTable)
            ->where(['name' => $name])
            ->one($this->db);
        if ($row === false) {
            return null;
        }
        $data = $row['data'];
        if (is_resource($data)) {
            $data = stream_get_contents($data);
        }

        return unserialize($data);
    }

to this

public function getRule($name)
    {
        if ($this->rules !== null) {
            return isset($this->rules[$name]) ? $this->rules[$name] : null;
        }

        $row = (new Query())->select(['data' => 'convert_from("data", \'UTF-8\')'])
            ->from($this->ruleTable)
            ->where(['name' => $name])
            ->one($this->db);
        if ($row === false) {
            return null;
        }
        $data = $row['data'];
        if (is_resource($data)) {
            $data = stream_get_contents($data);
        }

        return unserialize($data);
    }

how data stored in auth_rule table: image

any suggestion? why this happens?

Additional info

Q A
Yii version 2.0.40
PHP version 5.6
Operating system MacOS
Postgresql 13.2
bizley commented 3 years ago

This is well known problem with unserialize and utf8 data. I'm not sure if we can do much about it. Maybe switching to json would be better...

samdark commented 3 years ago

@bizley JSON isn't supported by all DBMS we have.

bizley commented 3 years ago

I was thinking more of a text column with json-encoded data than json column.

But...

I did some testing because I remembered that unserializing issue from way back and I realized everything works... as long as the data is utf8. Then I saw that OP is converting the data to utf8 in the database so this is the reason. While we can easily enforce "encoding" as UTF8 in MySQL (and this is done in RBAC migration) this is not that trivial for other DBs including PostgreSQL. So I think that first of all we should have it mentioned somewhere that UTF8 is really needed for that table, and second - maybe we can have rules not serialized in the DB?

samdark commented 3 years ago

Having rules not serialized sounds interesting. I wonder why we serialize them...

bizley commented 3 years ago

I believe (absolutely no data supporting this statement) that 99% of users are not having rules that require their data to be stored in DB. I think the same applies to the items with additional data property. Anyway, we could have only info, that a rule is used, stored in DB and then just instantiate its object when executing it is required. Having the rule object is required anyway and I cannot image a case where one rule has so many customizations that we need to serialize them and store the snapshots in DB.

Can anyone prove me wrong?

samdark commented 3 years ago

https://github.com/yiisoft/yii2/issues/13501