检查字符串是否序列化?

Dan*_*ang 129 php serialization

确定字符串是否是serialize()函数的结果/输出的最佳方法是什么?

Pas*_*TIN 183

我会说,尝试unserialize一下;-)

引用手册:

如果传递的字符串不可反序列化,则返回FALSE并发出E_NOTICE.

所以,你必须检查返回值是false或不是(有===!==,以确保不会有任何问题0null或任何等于false,我会说).

请注意通知:您可能需要/需要使用@运算符.

例如 :

$str = 'hjkl';
$data = @unserialize($str);
if ($data !== false) {
    echo "ok";
} else {
    echo "not ok";
}
Run Code Online (Sandbox Code Playgroud)

会得到你:

not ok
Run Code Online (Sandbox Code Playgroud)


编辑:哦,就像@Peter说的那样(感谢他!),如果你试图反序列化布尔值false的表示,你可能会遇到麻烦:-(

因此,检查序列化字符串是否不等于" b:0;"也可能有帮助; 我认为这样的事情可以解决问题:

$data = @unserialize($str);
if ($str === 'b:0;' || $data !== false) {
    echo "ok";
} else {
    echo "not ok";
}
Run Code Online (Sandbox Code Playgroud)

在尝试反序列化之前测试该特殊情况将是一种优化 - 但如果您通常没有错误的序列化值,则可能没那么有用.

  • 但是,如果未序列化的值是一个值为FALSE的布尔值,该怎么办? (18认同)
  • 重要信息:永远不要反序列化原始用户数据,因为它可以用作攻击媒介。[OWASP:PHP_Object_Injection](https://www.owasp.org/index.php/PHP_Object_Injection) (2认同)

Bra*_*ldt 55

我没有写这段代码,实际上是来自WordPress.以为我会把它包含在任何感兴趣的人中,它可能有点矫枉过正但它有效:)

<?php
function is_serialized( $data ) {
    // if it isn't a string, it isn't serialized
    if ( !is_string( $data ) )
        return false;
    $data = trim( $data );
    if ( 'N;' == $data )
        return true;
    if ( !preg_match( '/^([adObis]):/', $data, $badions ) )
        return false;
    switch ( $badions[1] ) {
        case 'a' :
        case 'O' :
        case 's' :
            if ( preg_match( "/^{$badions[1]}:[0-9]+:.*[;}]\$/s", $data ) )
                return true;
            break;
        case 'b' :
        case 'i' :
        case 'd' :
            if ( preg_match( "/^{$badions[1]}:[0-9.E-]+;\$/", $data ) )
                return true;
            break;
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

  • 当前的WordPress版本更为复杂:http://codex.wordpress.org/Function_Reference/is_serialized#Source_File (5认同)
  • +1给予学分.我不知道WordPress有这个内置的.感谢您的想法 - 我现在将继续使用WordPress Core创建有用功能的存档. (3认同)

SoN*_*9ne 17

优化Pascal MARTIN的反应

/**
 * Check if a string is serialized
 * @param string $string
 */
public static function is_serial($string) {
    return (@unserialize($string) !== false);
}
Run Code Online (Sandbox Code Playgroud)


Haz*_*oor 16

如果$ string是序列化false值,即$string = 'b:0;' SoN9ne的函数返回false,那就错了

所以功能就是

/**
 * Check if a string is serialized
 *
 * @param string $string
 *
 * @return bool
 */
function is_serialized_string($string)
{
    return ($string == 'b:0;' || @unserialize($string) !== false);
}
Run Code Online (Sandbox Code Playgroud)

  • 交换这些测试的顺序将更有效。 (2认同)

Pet*_*ley 13

尽管Pascal MARTIN的答案非常好,但我很好奇你是否可以采用另一种方式,所以我这样做只是为了一个心理练习

<?php

ini_set( 'display_errors', 1 );
ini_set( 'track_errors', 1 );
error_reporting( E_ALL );

$valueToUnserialize = serialize( false );
//$valueToUnserialize = "a"; # uncomment this for another test

$unserialized = @unserialize( $valueToUnserialize );

if ( FALSE === $unserialized && isset( $php_errormsg ) && strpos( $php_errormsg, 'unserialize' ) !== FALSE )
{
  echo 'Value could not be unserialized<br>';
  echo $valueToUnserialize;
} else {
  echo 'Value was unserialized!<br>';
  var_dump( $unserialized );
}
Run Code Online (Sandbox Code Playgroud)

它确实有效.唯一需要注意的是,如果你有一个注册的错误处理程序,它可能会因为$ php_errormsg的工作方式而中断.


cha*_*aos 11

$data = @unserialize($str);
if($data !== false || $str === 'b:0;')
    echo 'ok';
else
    echo "not ok";
Run Code Online (Sandbox Code Playgroud)

正确处理案件serialize(false).:)