PHP严格反序列化

时间:2018-08-03 09:32:43

标签: php serialization

我有一个带有错字的类,该类存储在MemCached中。这是示例:

class Person { public $n1ame; }
echo serialize(new Person());

我在下一个代码版本中修复了拼写错误:

class Person { public $name; }
var_dump(unserialize($previousSerializedPersion));

但是这是发生了什么:PHP向我的对象隐式添加了一个不存在的字段:

object(Person)#1 (2) {
  ["name"]=>
  NULL
  ["n1ame"]=>
  NULL
}

我的用户获得了包含数据的附加字段。我期望的是一个例外。

有什么办法可以实现?

1 个答案:

答案 0 :(得分:6)

三个建议:

1。)。在调用unserialize()之前,请对序列化的数据字符串执行手动字符串转换以进行更正。

O:6:"Person":1:{s:5:"n1ame";N;}

s:5是原始序列化中属性n1ame的字符长度,您需要将其更改为s:4才能将其还原回names用于字符串数据类型,数字是文本值的长度,在这种情况下为属性键。

O:6:"Person":1:{s:4:"name";N;}

您可以尝试

unserialize( str_replace( 's:5:"n1ame"', 's:4:"name"', $previousSerializedPersion ) );

2。)。另一个解决方案是__wakup()函数来更正数据。该函数在序列化之后但在分配和使用之前在您的对象上运行,这可能是一个“更好”的解决方案,因为它在代码中清晰地列出了。

class Person
{
  public $name;
  public function __wakeup()
  {
    if( property_exists( $this, 'n1ame' ) )
    {
      $this->name = $this->n1ame;
      unset( $this->n1ame );
    }
  }
}

unserialize('O:6:"Person":1:{s:5:"n1ame";s:4:"mark";}');

3。)。使用相同的__wakup()概念,但抛出异常。

class Person
{
  public $name;
  public function __wakeup()
  {
    if( property_exists( $this, 'n1ame' ) )
    {
      throw new Exception('oh no this data is bad');
    }
  }
}

unserialize('O:6:"Person":1:{s:5:"n1ame";s:4:"mark";}');

https://3v4l.org/h8pss