Хорошо, я запускаю публичный JSONP API, данные которого подаются с моего PHP-сервера. Я просто прочитал эту статью:
В принципе, если мои строки JSON содержат символ U + 2028 (разделитель строк Unicode) или символ U + 2029 (разделитель абзацев Unicode), то это совершенно допустимый JSON. Однако при использовании JSONP JSON запускается как JavaScript, и никакая строка в JavaScript не может содержать буквальный U + 2028 или U + 2029, так как он разрушит JavaScript. По-видимому, это обычно не проблема, если вы используете правильный JSON-парсер, но в случае JSONP браузер является парсером JSON.
По сути, если эти символы были внутри строк в моих JSONP-данных, отправляемых клиенту, это приведет к перерыву строки или абзаца в строку, которая приведет к поломке JavaScript и прекращению его выполнения. Это возможность, поскольку API отправляет обратно некоторые данные, введенные клиентом. Кто-то может потенциально ввести U + 2028 или U + 2029 в базу данных, поэтому, когда я отправлю это обратно как JSONP, он разрушит любую реализацию, используя мой API.
Итак, мой вопрос: на PHP, как я могу дезинфицировать / выводить данные JSON для удаления или удаления символов U + 2028 и U + 2029 перед отправкой его клиенту?
В настоящее время мой процесс выполняет json_encode в массиве данных и передает эти данные клиенту. Должен ли я избегать данных, перейдя через массив и отфильтровывая его, или сразу же удалите всю закодированную строку JSON?
Другое дело, я не уверен, как избежать символов U + 2028 и U + 2029 на PHP в любом случае. Могу ли я просто сделать str_replace? Я не уверен, что str_replace многобайт безопасен, и нет функции mb_str_replace, если я не использую какую-то пользовательскую. Итак, как вы удаляете / удаляете эти символы Unicode?
Огромное спасибо.
Вы можете заменить U+2028
, U+2029
на "\u2028"
, "\u2029"
либо на стороне PHP, либо на стороне JavaScript, или на обоих, это не имеет значения, если это происходит хотя бы один раз (это идемпотент) ,
Вы можете просто использовать обычные функции замены строк. Они не обязательно должны быть «многобилетными», и вы можете сделать это так же легко в любой кодировке Unicode (UTF-8, UTF-16, UTF-32 все одинаково хорошо). У PHP не было escape-последовательностей Unicode в прошлый раз, когда я проверил, что является еще одной причиной, по которой PHP является шуткой, но вы можете использовать escape \x
с UTF-8 …
(Короче говоря, причина, почему нет функции замены многобайтовой строки, состоит в том, что она будет избыточной – она будет точно такой же, как функция замены не многобайтовых строк).
// 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);
Или вы просто ничего не можете сделать, поскольку PHP по умолчанию json_encode()
символы, отличные от Unicode, в json_encode()
:
// Safe echo json_encode("\xe2\x80\xa9"); --> "\u2029" // Correct JSON, but invalid Javascript... // (Well, technically, JSON root must be array or object) echo json_encode("\xe2\x80\xa9", JSON_UNESCAPED_UNICODE); --> " "
Стоит отметить, что это уже не нужно.
По умолчанию json_encode()
кодирует все символы, отличные от ASCII (включая U + 2028 и U + 2029), а также избегает косой черты, даже если это не нужно избегать спецификацией JSON. Это не вредит побегу, и в определенных контекстах это может быть безопаснее. Таким образом, по умолчанию эти символы все равно экранируются.
Константа JSON_UNESCAPED_UNICODE
выводит JSON_UNESCAPED_UNICODE
Unicode, который может сохранять байты. Тем не менее, так же, как символ слэша экранирован, потому что он может быть опасным в некоторых контекстах, так и U + 2028 и U + 2029 также экранированы, потому что они тоже опасны в некоторых контекстах. Это было не так в то время, когда вы задали свой вопрос: эта функция была добавлена в PHP совсем недавно .
(Эти дополнительные экраны можно отключить с помощью JSON_UNESCAPED_SLASHES
и JSON_UNESCAPED_LINE_TERMINATORS
, соответственно.)