Ошибка не выдается, но несериализация PHP не выполняется успешно

#php #class #serialization

#php #класс #сериализация

Вопрос:

Ниже приведена часть класса, которую я сейчас пишу, которая должна позаботиться о сериализации. Функция serialize работает нормально, и создается соответствующая строка. Проблема заключается в функции десериализации ($data). Соответствующая сериализованная строка передается в функцию unserialize в функции deserialize. К сожалению, объект $ scl не содержит ожидаемых данных. Не выдается уведомление или ошибка. В результате $scl->PrintData() выводит информацию, но не содержимое переменных класса. В будущем я хотел бы присвоить результат несериализации $this. Чего я не понимаю?

 public function serialize() {
    $serial = serialize($this);
    $df = gzdeflate($serial);
    $b64 = base64_encode($df);
    $ue = urlencode($b64);
    return($ue);
}

public function deserialize($data) {
    $u64 = base64_decode($data);
    $gf = gzinflate($u64);
    $scl = unserialize($gf);   
    if(!$scl)
        echo"Cannot unserialize<br>";
    $scl->printData();
}
function __sleep() {
    return($this);
}
function __wakeup() {
    echo"Waking up";
}
public function printData() {
    echo"Data: <br>
    ID: {$this->ID} <br>
    sID: {$this->sID}<br>
    ...
    ";
}
  

Ответ №1:

__sleep предполагается, что возвращает массив ключей, которые должны быть сериализованы. Вы возвращаете объект.

Вы должны получать следующее уведомление:

serialize(): __sleep should return an array only containing the names of instance-variables to serialize.

Если вы этого не видите, убедитесь, что у вас полностью включено сообщение об ошибках.

Поскольку вместо массива ключей для сериализации возвращается объект, сериализованный объект в конечном итоге будет выглядеть примерно так:

 O:3:"Foo":1:{N;}
  

Foo было именем моего тестового класса, и N оно несериализовано в null . Вот почему вы теряете свои данные.

Если вы хотите сериализовать весь объект целиком, либо верните все свойства в виде массива из __sleep , либо не реализуйте это вообще. И это, и __wakeup являются полностью необязательными.

Если вы используете PHP 5.3, рассмотрите возможность реализации Serializable вместо этого, поскольку он имеет различные побочные эффекты, которые могут оказаться полезными при попытке запустить код для обработки эффектов сериализации и несериализации


Стоит отметить, что здесь вы можете столкнуться с огромной проблемой безопасности. Судя по кодировке URL, похоже, что в конечном итоге вы можете передавать сериализованные объекты через формы или URL-адреса. Это плохая, очень плохая идея, особенно если вы создаете пользовательскую обработку режима сна / пробуждения. Для злоумышленников это может быть средством внедрения произвольного кода (ссылка в формате PDF, начинается со страницы 28). Если вам абсолютно необходимо передавать сериализованные объекты в произвольном режиме, рассмотрите возможность использования реального шифрования и подписи данных с помощью HMAC.

Комментарии:

1. Это сработало хорошо 🙂 Я не смог присвоить результат несериализации $this now, это невозможно?

2. @jallmer, поправьте, вы никогда не сможете назначать что -либо $this -либо непосредственно, только свойствам. Кроме того, я добавил заключительный раздел к своему вопросу о важной проблеме безопасности.

3. Спасибо, я создал что-то вроде «конструктора копирования», который решил проблему. Теперь, когда это работает, я разберусь с проблемой безопасности.