37

URLクエリ文字列で多次元配列シンタックスを使用することは実際に安全/有効ですか?

http://example.com?abc[]=123&abc[]=456

すべてのブラウザで動作するようで、使用しても問題ないといつも思っていましたが、この記事のコメントによると、そうではありません:http ://www.456bereastreet.com/archive/201008/what_characters_are_allowed_unencoded_in_query_strings/#comment4

セカンドオピニオンを聞きたいです。

4

6 に答える 6

33

答えは簡単ではありません。

以下は、RFC3986のセクション3.2.2から抜粋したものです。

インターネットプロトコルリテラルアドレス、バージョン6
[RFC3513]以降で識別されるホストは、IPリテラル
を角かっこ("["および"]")で囲むことによって区別されます。
これは、URI構文で角括弧文字が許可される唯一の場所です。

これは、URIの他の場所では角かっこは使用できないことを明確に示すことで質問に答えているようです。ただし、角括弧文字とパーセントエンコードされた角括弧文字には違いがあります。

以下は、RFC3986のセクション3の冒頭から抜粋したものです。

  1. 構文コンポーネント

    一般的な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に違反しているように見えます。

于 2016-09-02T14:03:04.167 に答える
11

RFC 3986によると、URLのクエリコンポーネントには次の文法があります。

*( pchar / "/" / "?" )

同じRFCの付録Aから:

pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
[...]
pct-encoded   = "%" HEXDIG HEXDIG

unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
[...]    
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
             / "*" / "+" / "," / ";" / "="

これについての私の解釈は、そうでないものはすべて次のようになります。

 ALPHA / DIGIT / "-" / "." / "_" / "~" / 
     "!" / "$" / "&" / "'" / "(" / ")" / 
     "*" / "+" / "," / ";" / "=" / ":" / "@"

... pctエンコード、つまりパーセントエンコードする必要があります。したがって[]RFC 3986に準拠するように、パーセントエンコードする必要があります。

于 2012-07-15T08:11:28.567 に答える
8

DavidN.Jafferianの答えは素晴らしいです。いくつかの更新と実用的なメモを追加したいだけです。

  1. 長年にわたり、すべてのブラウザは、サーバーにリクエストを送信するときに、クエリ文字列に角かっこをエンコードせずに残してきました。(出典:https ://bugzilla.mozilla.org/show_bug.cgi?id = 1152455#c6 )。そのため、Webの大部分がこの動作に依存するようになり、変更される可能性は非常に低いと思います。

  2. 少なくともWebの目的ではRFC3986に取って代わると見なすことができる、WHATWG URL標準を読んだところ、エンコードせず、クエリ文字列でこの動作を体系化したということ[です]

編集:コメントやその他の回答に基づいて、WHATWG URL標準のより正確な解釈は、エンコード[されていない/無効であるということですが、受信/解析時に許容されるべきであり、そのように解析されたら、エンコードせずに再シリアル化する必要があります。]

于 2018-04-12T21:31:22.133 に答える
4

理想的にはイーサンの答えについて本当にコメントしたいのですが、それを行うのに十分な評判がありません。

ここでWHATWGURL標準の関連部分が参照されているかどうかはわかりません。正しい部分は、有効なURLクエリ文字列の定義にあると思います。これは、 URLコードポイントパーセントエンコードされたバイトから形成されるURLユニットで構成されていると説明しています。角かっこはURLコードポイント内にリストされているため、パーセントエンコードされたバイトのカテゴリに分類されます。

したがって、元の質問への回答では、角かっこがパーセントエンコードされている場合([の場合は%5B、]の場合は%5Dとして) 、URLのクエリ部分内の多次元配列構文(つまり、角かっこを使用して配列のインデックスを表す)が有効です。 )。

于 2019-01-31T11:53:17.747 に答える
2

角かっこはとにかく一級市民ではないという私の理解。引用は次のとおりです: https ://www.rfc-editor.org/rfc/rfc1738

ゲートウェイや他のトランスポートエージェントがそのような文字を変更することがあることが知られているため、他の文字は安全ではありません。これらの文字は、「{」、「}」、「|」、「」、「^」、「〜」、「[」、「]」、および「`」です。

于 2015-03-23T13:18:38.493 に答える
1

配列を渡さなければならないとき、私はいつもその種のクエリに行きたくなりましたが、私はそれを避けました。理由は次のとおりです。

  • RFCで定義されているようにクリアされていません。
  • 言語が異なれば、解釈も異なる場合があります。

配列を渡すためのオプションがいくつかあります。

  • 配列の文字列表現をエンコードします(JSONは?)
  • 「val1=blah&val2 = blah&..」などのパラメータを使用します。

また、使用している言語がわかっている場合は、(安全に)使用している種類のクエリ文字列を選択できます(%エンコードする必要があるだけです[])。

于 2012-07-15T08:15:38.920 に答える