【问题标题】:Unserializing PHP array not working反序列化 PHP 数组不起作用
【发布时间】:2018-02-02 17:38:25
【问题描述】:

我在 MySQL longblob 数据字段中存储了以下序列化数组:

a:1:{s:10:"attributes";a:1:{s:13:"Ticket Holder";a:1:{i:0;s:8:"Joe Blow";}}}

在 PHP 中,当我查询字段、反序列化并打印出来时,会打印出以下空数组:

Array
(
)

这是表创建语句:

CREATE TABLE `order` (
  `state` varchar(255) CHARACTER SET ascii DEFAULT NULL,
  `data` longblob,
  `created` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

【问题讨论】:

  • 你用什么代码来反序列化它?
  • 你使用什么函数来执行查询和反序列化?
  • 它在 Drupal 8 中。我正在使用 \Drupal\Core\Database\Connection 中的 select 函数进行查询。我只是使用 PHP 反序列化函数来反序列化它。
  • 在phpfiddle中试过,unserialize()抛出异常。如果我复制数组并对其进行序列化,我会得到a:1:{s:10:"attributes";a:1:{s:13:"ticket holder";a:1:{i:0;s:8:"Joe Blow";}}} 底线:我认为你得到的数据有问题
  • 出于隐私考虑,我更改了持票人姓名。这是我的序列化代码 serialize(['attributes' => ['Ticket Holder' => ['Joe Blow']]])。

标签: php mysql deserialization blob


【解决方案1】:

您的序列化数据无效。您绝不能手动对序列化数据进行 mainpulate。

字符串被序列化为:

s:<i>:"<s>";

其中&lt;i&gt;是一个整数,表示&lt;s&gt;的字符串长度,&lt;s&gt;是字符串值。

所以在这种情况下,有效数据是:

a:1:{s:10:"attributes";a:1:{s:13:"Ticket Holder";a:1:{i:0;s:8:"Joe Blow";}}}

Joe Blow 字符串长度为 8,但在您的序列化字符串中定义为 13。

见:Structure of a Serialized PHP string

【讨论】:

  • 来自 OP:“s:13:"Joe Blow" 已更改为提出此问题。原名称有 13 个字符”
  • 请在您的问题中将Joe Blow替换为另一个有效字符串,以防出错。
  • 很抱歉造成混乱 Alireza。谢谢。
【解决方案2】:

在 SELECT 语句中将列转换为 UTF8,然后对其进行反序列化。

CONVERT (data USING utf8)

我不知道为什么这是必要的。我猜它与 utf8mb4_general_ci 排序规则有关。

感谢大家的帮助!

【讨论】:

    【解决方案3】:

    使用base64_encode

    核心问题来自数据库完成的二进制编码以及它添加到存储值的额外字节。这会“破坏”从数据库中获取的数据并导致unserialize 失败。为了帮助缓解这个问题,您可以使用base64_encodebase64_decode,这将允许您轻松插入和提取数据。

    // data is encoded before insert
    $dataToInsert = base64_encode(serialize($myArray));
    
    // decode the data before unserializing it
    $dataToRead = unserialize(base64_decode($longblob));
    

    【讨论】:

    • @bishop 问题来自longblob 类型完成的编码,这使得数据损坏,进而导致unserialize 失败。使用base64_encodebase64_decode 可以防止这种情况发生
    • 我试过了,它只存储 a:0:{} 之外的任何内容。不使用 base64 编码时,它会正确存储序列化数组。我只是无法从 longblob 字段中检索它。谢谢威廉。
    • 如果 OP 在没有正确转义的情况下将数据插入到他的数据库中,那么对序列化 PHP 进行 base64 编码可能会解决直接问题,但这不适用于存储在数据库中的所有数据 - 并暗示该代码易受 SQL 注入攻击。仅使用 longblob 不会损坏数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-23
    • 2012-07-11
    • 2011-08-11
    • 1970-01-01
    • 1970-01-01
    • 2020-10-16
    相关资源
    最近更新 更多