逃避逃脱角色

Ali*_*xel 9 php json escaping str-replace

我试图模仿json_encodePHP 5.3.0中实现的位掩码标志,这是我的字符串:

$s = addslashes('O\'Rei"lly'); // O\'Rei\"lly
Run Code Online (Sandbox Code Playgroud)

json_encode($s, JSON_HEX_APOS | JSON_HEX_QUOT)输出如下:

"O\\\u0027Rei\\\u0022lly"
Run Code Online (Sandbox Code Playgroud)

我目前正在使用早于5.3.0的PHP版本:

str_replace(array('\\"', "\\'"), array('\\u0022', '\\\u0027'), json_encode($s))
or
str_replace(array('\\"', '\\\''), array('\\u0022', '\\\u0027'), json_encode($s))
Run Code Online (Sandbox Code Playgroud)

哪个正确输出相同的结果:

"O\\\u0027Rei\\\u0022lly"
Run Code Online (Sandbox Code Playgroud)

我无法理解为什么我需要更换单引号('\\\''甚至是"\\'"[ 不包括周围的引号 ])'\\\u0027'而不仅仅是'\\u0027'.


这是我在移植到PHP <5.3时遇到问题的代码:

if (get_magic_quotes_gpc() && version_compare(PHP_VERSION, '6.0.0', '<'))
{
    /* JSON_HEX_APOS and JSON_HEX_QUOT are availiable */
    if (version_compare(PHP_VERSION, '5.3.0', '>=') === true)
    {
        $_GET = json_encode($_GET, JSON_HEX_APOS | JSON_HEX_QUOT);
        $_POST = json_encode($_POST, JSON_HEX_APOS | JSON_HEX_QUOT);
        $_COOKIE = json_encode($_COOKIE, JSON_HEX_APOS | JSON_HEX_QUOT);
        $_REQUEST = json_encode($_REQUEST, JSON_HEX_APOS | JSON_HEX_QUOT);
    }

    /* mimic the behaviour of JSON_HEX_APOS and JSON_HEX_QUOT */
    else if (extension_loaded('json') === true)
    {
        $_GET = str_replace(array(), array('\\u0022', '\\u0027'), json_encode($_GET));
        $_POST = str_replace(array(), array('\\u0022', '\\u0027'), json_encode($_POST));
        $_COOKIE = str_replace(array(), array('\\u0022', '\\u0027'), json_encode($_COOKIE));
        $_REQUEST = str_replace(array(), array('\\u0022', '\\u0027'), json_encode($_REQUEST));
    }

    $_GET = json_decode(stripslashes($_GET));
    $_POST = json_decode(stripslashes($_POST));
    $_COOKIE = json_decode(stripslashes($_COOKIE));
    $_REQUEST = json_decode(stripslashes($_REQUEST));
}
Run Code Online (Sandbox Code Playgroud)

awa*_*tts 13

PHP字符串

'O\'Rei"lly'
Run Code Online (Sandbox Code Playgroud)

只是PHP获取字面值的方法

O'Rei"lly
Run Code Online (Sandbox Code Playgroud)

成为可以使用的字符串.调用addslashes该字符串会将其更改为以下11个字符

O\'Rei\"lly
Run Code Online (Sandbox Code Playgroud)

strlen(addslashes('O\'Rei"lly')) == 11

这是发送给的值json_escape.

在JSON中,反斜杠是一个转义字符,因此需要进行转义,即

\ 成为 \\

单引号和双引号也可能导致问题.因此,以一种方式将它们转换为等效的unicode,以避免出现问题.所以后来PHP的json_encode版本发生了变化

' 成为 \u0027

" 成为 \u0022

所以应用这三个规则

O\'Rei\"lly
Run Code Online (Sandbox Code Playgroud)

给我们

O\\\u0027Rei\\\u0022lly
Run Code Online (Sandbox Code Playgroud)

然后将此字符串包装在双引号中,使其成为JSON字符串.替换表达式包括前导斜杠.无论是偶然还是故意,这意味着返回的前导和尾随双引号json_encode不受转义的影响,它不应该是.

所以在早期版本的PHP中

$s = addslashes('O\'Rei"lly');
print json_encode($s);
Run Code Online (Sandbox Code Playgroud)

会打印

"O\\'Rei\\\"lly"
Run Code Online (Sandbox Code Playgroud)

我们希望改变'为be \u0027 ,我们希望改变\"\u0022因为\in \"只是为了"进入字符串,因为它以双引号开头和结尾.

这就是我们得到的原因

"O\\\u0027Rei\\\u0022lly"
Run Code Online (Sandbox Code Playgroud)