没有抛出错误,但是PHP反序列化没有成功


No error is thrown but PHP unserialization doesn't succeed

下面是我目前正在编写的类的一部分,它应该负责序列化。serialize函数工作正常,并生成一个合适的字符串。问题出在反序列化($data)函数中。在反序列化函数中传递正确的序列化字符串以进行反序列化。不幸的是,$scl对象不包含预期的数据。没有提示或错误被抛出。结果是$scl->printData()打印信息,但不打印类变量的内容。将来我想把unserialize的结果赋值给$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>
    ...
    ";
}

__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对数据签名。