【问题标题】:storing php objects on html form element and passing php objects through GET method?在 html 表单元素上存储 php 对象并通过 GET 方法传递 php 对象?
【发布时间】:2011-03-25 17:13:53
【问题描述】:

我可能听起来有点奇怪,但是,有什么办法吗?例如,我有一个 PHP 对象$foo

有没有办法通过一些对象加密函数将这个对象存储在 HTML 表单(隐藏输入)中,然后用解密函数检索。

同样,我可以通过 GET 方法传递这些对象吗?

【问题讨论】:

    标签: php forms


    【解决方案1】:

    就像其他地方已经指出的那样,您可以使用序列化将对象转换为字符串。

    $foo = (object) array(
        'foo' => 'foo & bär',
        'bar' => new StdClass
    );
    
    $serialized = serialize($foo);
    

    这给出了:

    O:8:"stdClass":2:{s:3:"foo";s:10:"foo & bär";s:3:"bar";O:8:"stdClass":0:{}}
    

    如您所见,该字符串中有引号,因此您不能将其插入链接而不冒破坏标记的风险:

    <a href="http://example.com?s=O:8:" <-- quote closes href
    

    所以至少你必须htmlspecialcharsurlencode 那个输出。但是,这仍然会使内容易于阅读。您可以使用PHP's MCrypt library 对字符串进行一些强加密。但如果数据真的那么敏感,您可能应该找到另一种传输方式,远离您网站的面向公众的部分。

    如果数据不那么敏感,那么您可以通过混淆字符串来保护一些 CPU 周期。最简单的方法是通过gzdeflate 运行它:

    echo gzdeflate(serialize($foo));
    

    给出类似的东西

    ?R*.Iq�I,.V�2��.�2�RJ��W�.�24 …
    

    使用gzdeflate 也会缩短大的序列化字符串。缺点是,它会产生不适合通过 HTTP 传输的输出,因此您还必须 base64_encode 表示:

    echo base64_encode(gzdeflate(serialize($foo)));
    

    然后会给出

    87eysFIqLklxzkksLlayMrKqLrYytlJKy89Xsi62MjQAMxXUFJIOLykCiQDlkhKBLH9UfQZW1bW1AA==
    

    这对于传输是安全的,并且与原始序列化字符串相比也相当模糊。因为我们在对字符串进行 base64 处理之前已经对其进行了压缩,所以任何聪明到能确定它是 base64 的人在尝试反转压缩字符串时仍然必须理解压缩字符串。

    要将字符串转回一个对象,你可以这样做

    unserialize(
        gzinflate(
            base64_decode(
                $obfuscatedString
            )
        )
    )
    

    然后取回你的对象。 Demo


    关于安全性的说明

    以上内容仍然不安全。您不应该依赖混淆来确保安全。如果通过 HTTP 传输一个对象或整个对象图,则必须将它们视为接收端的用户输入。 用户输入不可信。弄清楚字符串是如何被混淆的恶意用户可以提供更改的输入。因为您要将对象反序列化回程序流中,所以您必须对生成的对象绝对偏执。

    有关相关示例,请参阅 http://www.sektioneins.com/en/advisories/advisory-032009-piwik-cookie-unserialize-vulnerability/

    【讨论】:

      【解决方案2】:

      如果它不包含敏感数据,你可以serialize()它(甚至可以选择加密序列化数据),例如:

      <input type="hidden" name="foo" value="<?php echo htmlspecialchars(serialize($foo), ENT_QUOTES); ?>" />
      

      在接收脚本中,unseralize()将POST数据取回对象:

      $foo = unserialize($_POST['foo']);
      

      【讨论】:

      • 可能还需要在序列化之后转义,但在回显之前以防止脚本/HTML 注入等,即htmlspecialchars(serialize($foo))。要在 PHP 中获取值,您需要先将该表单发送到 PHP,然后您可以通过 unserialize($_POST['foo'])(或 unserialize($_GET['foo']),如果您通过 GET 发送)读取它 - 但是请注意,unserialize() 已经暴露了安全问题如果我没记错的话在过去,所以这可能很危险,您还必须检查反序列化是否真的有效。
      • @explorex:更新了我的答案。 @Archimedix:谢谢。
      • 在我的例子中,反序列化的 var_dump 是“bool(false)”。可能出了什么问题?我将表单变量值用作 .. value=""
      • 我也使用了 htmlspecialchars(..) ,就像你上面的代码中提到的那样,但是反序列化的结果也是错误的。我试图通过值传递一个自定义的 php 对象。跨度>
      【解决方案3】:

      您可以使用serializeunserialize 方法:

      $serialized = serialize($foo);
      

      现在您可以将$serialized 存储在隐藏的输入字段中。稍后,您可以将其读回并使用unserialize 方法转换为对象。例如:

      $foo = unserialize($_POST['my_hidden_field']); // back to object
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-28
        • 1970-01-01
        • 1970-01-01
        • 2018-02-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多