Как заменить/избежать U + 2028 или U + 2029 символов в PHP, чтобы остановить мой JSONP API - программирование
Подтвердить что ты не робот

Как заменить/избежать U + 2028 или U + 2029 символов в PHP, чтобы остановить мой JSONP API

Хорошо. Я запускаю публичный API JSONP, данные которого подаются с моего 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 является многобайтовой безопасностью, а функция no mb_str_replace, если я не использую какой-то пользовательский. Итак, как вы удаляете/удаляете эти символы Unicode?

Большое спасибо.

4b9b3361

Ответ 1

Вы можете заменить U+2028, U+2029 на "\u2028", "\u2029" либо на стороне PHP, либо на стороне JavaScript, либо на обоих, это не имеет значения, если это происходит хотя бы один раз (это idempotent).

Вы можете просто использовать обычные функции замены строк. Они не обязательно должны быть "многобилетными", и вы можете сделать это так же легко в любой кодировке 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 вытесняет символы, отличные от 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);
--> "
"

Ответ 2

Стоит отметить, что это уже не нужно.

По умолчанию json_encode() кодирует все символы, отличные от ASCII (включая U + 2028 и U + 2029), а также избегает передняя косая черта, даже если это не нужно избегать спецификации JSON. Это не вредит побегу, и в определенных контекстах это может быть безопаснее. Таким образом, по умолчанию эти символы все равно экранируются.

Константа JSON_UNESCAPED_UNICODE выводит unescaped Unicode, который может сохранять байты. Тем не менее, так же, как символ косой черты экранируется, поскольку в некоторых контекстах это может быть опасно, так и U + 2028 и U + 2029 также экранированы, потому что они тоже опасны в некоторых контекстах. Это было не так в то время, когда вы задали свой вопрос: эта функция была добавлена ​​в PHP в последнее время.

(Эти дополнительные экраны можно отключить с помощью JSON_UNESCAPED_SLASHES и JSON_UNESCAPED_LINE_TERMINATORS, соответственно.)