URLクエリ文字列で多次元配列シンタックスを使用することは実際に安全/有効ですか?
http://example.com?abc[]=123&abc[]=456
すべてのブラウザで動作するようで、使用しても問題ないといつも思っていましたが、この記事のコメントによると、そうではありません: http://www.456bereastreet.com/archive/201008/what_characters_are_allowed_unencoded_in_query_strings/#コメント4
セカンドオピニオンを聞きたいです。
答えは簡単ではありません。
以下は、RFC3986のセクション3.2.2から抜粋したものです。
インターネットプロトコルリテラルアドレス、バージョン6で識別されるホスト
[RFC3513]以降は、IPリテラルを囲むことで区別されます
角括弧内( "["および "]")。これは唯一の場所です
URI構文では角括弧文字を使用できます。
これそうです角括弧はURIの他の場所では許可されていないことをフラットに述べることによって質問に答えます。ただし、角括弧文字とパーセントエンコードされた角括弧文字には違いがあります。
以下は、RFC3986のセクション3の冒頭から抜粋したものです。
構文コンポーネント
一般的なURI構文は、次の階層シーケンスで構成されます。
スキーム、権限、パス、クエリ、および
断片。URI =スキーム ":" hier-part ["?"クエリ] ["#"フラグメント]
したがって、「クエリ」は「URI」のコンポーネントです。
以下は、RFC3986のセクション2.2から抜粋したものです。
2.2。予約文字
URIには、で区切られたコンポーネントとサブコンポーネントが含まれます
「予約済み」セットの文字。これらの文字は呼ばれます
「予約済み」は、によって区切り文字として定義される場合と定義されない場合があるためです。
一般的な構文、各スキーム固有の構文、または
URIの間接参照アルゴリズムの実装固有の構文。
URIコンポーネントのデータが予約済みと競合する場合
区切り文字としての文字の目的、次に競合するデータは
URIが形成される前にパーセントエンコードされます。reserved = gen-delims / sub-delims gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
したがって、角かっこはクエリ文字列に表示される場合がありますが、パーセントエンコードされている場合に限ります。そうでない場合を除いて、セクション2.2でさらに説明します。
URIを生成するアプリケーションは、データオクテットをパーセントエンコードする必要があります。
これらの文字を除いて、予約済みセットの文字に対応します
URIスキームによって、その中のデータを表すことが特に許可されています
成分。予約文字がURIコンポーネントで見つかった場合
そのキャラクターの区切りの役割は知られていないので、
それに対応するデータオクテットを表すと解釈されます
US-ASCIIでの文字のエンコード。
したがって、角かっこは「ホスト」サブコンポーネントでのみ許可されるため、RFC 3986でエンコードされていない角かっこでデータを表すことが明示的に許可されていない限り、他のコンポーネントやサブコンポーネント、この場合は「クエリ」コンポーネントでパーセントエンコードする必要があります。クエリコンポーネントはありません。
ただし、「URI生成アプリケーション」が「すべき」ことを実行できない場合、クエリで角かっこをエンコードしないままにしておくと、URIの読者はURIを完全に拒否することはありません。代わりに、角かっこはクエリコンポーネントのデータに属していると見なされます。これは、角かっこがそのコンポーネントの区切り文字として使用されていないためです。
これが、たとえば、PHPがエンコードされていない角括弧とエンコードされたパーセント角括弧の両方をクエリ文字列の有効な文字として受け入れ、それらに特別な目的を割り当てる場合、RFC3986の違反ではない理由です。 。ただし、角括弧をパーセントエンコードしないことでこの抜け穴を利用しようとする作成者は、RFC3986に違反しているように見えます。
RFC 3986によると、URLの クエリコンポーネント の文法は次のとおりです。
*( pchar / "/" / "?" )
同じRFCの 付録A から:
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
[...]
pct-encoded = "%" HEXDIG HEXDIG
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
[...]
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="
これについての私の解釈は、そうでないものはすべて次のようになります。
ALPHA / DIGIT / "-" / "." / "_" / "~" /
"!" / "$" / "&" / "'" / "(" / ")" /
"*" / "+" / "," / ";" / "=" / ":" / "@"
... pctエンコード、つまりパーセントエンコードする必要があります。したがって、[
および]
は、RFC3986に準拠するようにパーセントエンコードする必要があります。
David N.Jafferianの答えは素晴らしいです。いくつかの更新と実用的なメモを追加したいだけです。
長年にわたり、すべてのブラウザは、サーバーにリクエストを送信するときに、クエリ文字列に角かっこをエンコードせずに残してきました。 (出典: https://bugzilla.mozilla.org/show_bug.cgi?id=1152455#c6 )。そのため、Webの大部分がこの動作に依存するようになり、変更される可能性は非常に低いと思います。
少なくともWebの目的ではRFC3986に取って代わると見なすことができる、WHATWG URL標準を読んだところ、クエリ文字列で[
と]
をエンコードしないというこの動作が体系化されています。関連する部分は次のとおりです。 https://url.spec.whatwg.org/#query-state 、これらの文字のパーセントエンコードについては言及していません。
理想的には イーサンの答え についてコメントしたいのですが、それを行うのに十分な評判がありません。
ここでWHATWGURL標準の関連部分が参照されているかどうかはわかりません。正しい部分は、有効な URLクエリ文字列 の定義にあると思います。これは、 URLユニット それ自体は URLコードポイント と パーセントエンコードされたバイト から形成されます。角かっこはURLコードポイント内にリストされているため、パーセントエンコードされたバイトのカテゴリに分類されます。
したがって、元の質問への回答では、URLのクエリ部分内の多次元配列構文(つまり、角かっこを使用して配列のインデックスを表す)は有効です。角かっこがパーセントエンコードされている場合(%5Bとして) [および%5Dの場合])。
角括弧はとにかく一級市民ではないという私の理解。引用は次のとおりです。 http://tools.ietf.org/html/rfc1738
ゲートウェイや他のトランスポートエージェントがそのような文字を変更することがあることが知られているため、他の文字は安全ではありません。これらの文字は、「{」、「}」、「|」、「\」、「^」、「〜」、「[」、「]」、および「 `」です。
配列を渡さなければならないとき、私はいつもその種のクエリに行きたくなりましたが、私はそれを避けました。理由は次のとおりです。
配列を渡すには、いくつかのオプションがあります。
また、使用している言語が確実な場合は、(安全に)使用している種類のクエリ文字列を選択できます(%-encode []
も)。