web-dev-qa-db-ja.com

PHPのU + 2028またはU + 2029文字を置き換え/エスケープして、JSONPAPIの破損を防ぐ方法

わかりました。データがPHPサーバーから提供されるパブリックJSONPAPIを実行しています。この記事を読んだばかりです。

基本的に、JSON文字列にU + 2028文字(Unicode行区切り文字)またはU + 2029文字(Unicode段落区切り文字)が含まれている場合、これは完全に有効なJSONです。ただし、JSONPを使用する場合、JSONはJavaScriptとして実行され、JavaScriptを壊すため、JavaScriptの文字列にリテラルU +2028またはU + 2029を含めることはできません。どうやら、適切なJSONパーサーを使用している限り、これは通常問題ではありませんが、JSONPの場合、ブラウザーJSONパーサーです。

基本的に、これらの文字がクライアントに送信されるJSONPデータの文字列内にある場合、これにより文字列に行または段落の区切りがスローされ、JavaScriptが破損して実行が停止します。これは、APIがクライアントが入力したデータを送り返す可能性があるためです。誰かがU + 2028またはU + 2029をデータベースに入力する可能性があるため、それをJSONPとして返送すると、APIを使用した実装が破損します。

だから私の質問は、PHPでJSONデータをサニタイズ/出力エスケープして、クライアントに送信する前にU +2028およびU + 2029文字を削除またはエスケープするにはどうすればよいですか?

現在、私のプロセスはデータの配列に対して json_encode を実行し、そのデータをクライアントに送信しています。配列をループしてフィルタリングすることでデータをエスケープする必要がありますか、それともすべてのJSONエンコード文字列を一度にエスケープする必要がありますか?

もう1つは、PHP)のU +2028文字とU + 2029文字をエスケープする方法がわからないことです。str_replaceを実行できますか?str_replaceがマルチバイトかどうかわかりません。安全で、カスタムメイドの関数を使用しない限り、 mb_str_replaceなし 関数があります。では、これらのUnicode文字をどのように削除/エスケープしますか?

どうもありがとう。

20
zuallauz

PHP側またはJavaScript側、あるいはその両方で、U+2028U+2029"\u2028""\u2029"に置き換えることができます。少なくとも1回発生する限り、問題ではありません(べき等です)。

通常の文字列置換関数を使用できます。これらは「マルチバイトセーフ」である必要はなく、どのUnicodeエンコーディングでも同じように簡単に実行できます(UTF-8、UTF-16、UTF-32はすべて同じように問題ありません)。 PHP前回チェックしたときにUnicodeエスケープシーケンスがありませんでした。これは、PHPが冗談ですが、UTFで\xエスケープを使用できるもう1つの理由です。 -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文字をエスケープするため、何もすることはできません。

// 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);
--> "
"
22
Dietrich Epp

これはもはや必要ないことを指摘する価値があります。

デフォルトでは、 json_encode()all非ASCII文字(U +2028およびU + 2029を含む)をエンコードします)、また、JSON仕様でエスケープする必要がない場合でも、スラッシュをエスケープします。それを逃れることは害はなく、特定の状況ではより安全になる可能性があります。したがって、デフォルトでは、これらの文字はとにかくエスケープされます。

JSON_UNESCAPED_UNICODE定数は、エスケープされていないUnicodeを出力します。これにより、バイトを節約できます。ただし、状況によっては危険な場合があるためスラッシュ文字がエスケープされるのと同じように、U +2028とU + 2029もまたエスケープされます。それらも状況によっては危険です。あなたが質問をしたときはそうではありませんでした: この機能はPHP最近 に追加されました。

(これらの追加のエスケープは、それぞれJSON_UNESCAPED_SLASHESおよびJSON_UNESCAPED_LINE_TERMINATORSでオフにできます。)

0
TRiG