如何在PHP中替换/转义U+2028或U+2029字符,以防止我的JSONP API中断

17 浏览
0 Comments

如何在PHP中替换/转义U+2028或U+2029字符,以防止我的JSONP API中断

好的,我正在运行一个公共的JSONP API,数据是由我的PHP服务器提供的。我刚刚读到了这篇文章:\n

\n基本上,如果我的JSON字符串包含U+2028字符(Unicode换行符)或U+2029字符(Unicode段落分隔符),那么这是有效的JSON。然而,在使用JSONP时,JSON会被执行为JavaScript,而JavaScript中的字符串不能包含文字U+2028或U+2029,否则会导致JavaScript出错。据说,只要使用正确的JSON解析器,通常这不是一个问题,但是在JSONP的情况下,浏览器是JSON解析器。\n基本上,如果这些字符在我发送给客户端的JSONP数据的字符串中,它们会在字符串中引入换行或段落分隔符,这将导致JavaScript出错并停止执行。由于API返回了一些客户输入的数据,这种情况是可能的。有人可能会在数据库中输入U+2028或U+2029,因此当我将其作为JSONP返回时,任何使用我的API的实现都会出错。\n所以我的问题是,在PHP中,我应该如何对JSON数据进行清理/输出转义,以在发送给客户端之前删除或转义U+2028和U+2029字符?\n目前,我的过程是对数据数组进行json_encode,然后将该数据发送到客户端。我应该通过循环遍历数组并过滤数据来转义数据,还是一次性转义所有JSON编码的字符串?\n另外,我不确定如何在PHP中转义U+2028和U+2029字符。我可以使用str_replace吗?我不确定str_replace是否支持多字节,并且除非我使用自定义函数,否则没有mb_str_replace函数可用。那么,你如何删除/转义这些Unicode字符呢?\n非常感谢。

0
0 Comments

问题的原因是在PHP中,json_encode()默认会对非ASCII字符进行编码,并且会转义斜杠。虽然根据JSON规范,斜杠不需要进行转义,但转义斜杠在某些情况下可以提高安全性。因此,默认情况下,这些字符都会被转义。

解决方法是使用JSON_UNESCAPED_UNICODE常量来输出未转义的Unicode字符,这样可以节省字节。然而,就像斜杠字符因为在某些上下文中可能危险而被转义一样,U+2028和U+2029字符在某些上下文中也是危险的,因此它们也被转义。这在您提问的时候并不是这样的,这个功能是最近在PHP中添加的。

(可以使用JSON_UNESCAPED_SLASHESJSON_UNESCAPED_LINE_TERMINATORS来关闭这些额外的转义。)

0
0 Comments

问题的出现原因是因为在PHP中使用json_encode()函数时,默认会对非Unicode字符进行转义,但是对于U+2028和U+2029这两个字符,PHP并不会进行转义,导致JSONP API出现错误。

解决方法是可以在PHP端或JavaScript端使用字符串替换函数将U+2028和U+2029替换成"\u2028"和"\u2029",只要至少替换一次即可。代码示例如下:

// JavaScript
data = data.replace("\u2028", "\\u2028").replace("\u2029", "\\u2029");
// PHP
$data = str_replace("\xe2\x80\xa8", '\\u2028', $data);
$data = str_replace("\xe2\x80\xa9", '\\u2029', $data);

另一种解决方法是直接使用json_encode()函数,默认会对非Unicode字符进行转义。但是需要注意,默认情况下json_encode()函数假设使用UTF-8字符编码,如果使用其他字符编码可能会导致错误。代码示例如下:

// Safe
echo json_encode("\xe2\x80\xa9");  // 输出 "\u2029"
// 使用 JSON_UNESCAPED_UNICODE 参数,可以输出正确的JSON,但是在JavaScript中是无效的
echo json_encode("\xe2\x80\xa9", JSON_UNESCAPED_UNICODE);  // 输出 "
"

最后,需要注意的是,JSON允许使用UTF-8、UTF-16LE、UTF-16BE、UTF-32LE或UTF-32BE等编码,不需要指定使用哪种编码,因为可以通过检查前两个字符是否为ASCII字符来区分编码类型。

0