在 URL 查询字符串中使用多维数组合成器实际上是安全/有效的吗?
http://example.com?abc[]=123&abc[]=456
它似乎适用于每个浏览器,我一直认为它可以使用,但根据本文中的评论,它不是:http ://www.456bereastreet.com/archive/201008/what_characters_are_allowed_unencoded_in_query_strings/#comment4
我想听听第二个意见。
在 URL 查询字符串中使用多维数组合成器实际上是安全/有效的吗?
http://example.com?abc[]=123&abc[]=456
它似乎适用于每个浏览器,我一直认为它可以使用,但根据本文中的评论,它不是:http ://www.456bereastreet.com/archive/201008/what_characters_are_allowed_unencoded_in_query_strings/#comment4
我想听听第二个意见。
答案并不简单。
以下内容摘自 RFC 3986 的第 3.2.2 节:
由 Internet 协议文字地址(版本 6
[RFC3513] 或更高版本)标识的主机通过将 IP 文字
括在方括号(“[”和“]”)中来区分。
这是URI 语法中唯一允许使用方括号字符的地方。
这似乎通过直截了当地说明 URI 中的其他任何地方都不允许使用方括号来回答这个问题。但是方括号字符和百分比编码的方括号字符之间是有区别的。
以下内容摘自 RFC 3986 第 3 节的开头:
语法组件
通用 URI 语法由
称为方案、权限、路径、查询和
片段的组件的分层序列组成。URI = 方案“:”层次部分 [“?” 查询] [“#”片段]
所以“查询”是“URI”的一个组成部分。
以下内容摘自 RFC 3986 的第 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 接受未编码和百分比编码的方括号作为查询字符串中的有效字符,甚至为它们分配特殊用途时,这并不违反 RFC 3986。然而,试图利用这个漏洞而不是对方括号进行百分比编码的作者似乎违反了 RFC 3986。
根据 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 进行百分比编码。
David N. Jafferian 的回答非常棒。我只想添加一些更新和实用说明:
多年来,每个浏览器在向服务器提交请求时都会在未编码的查询字符串中留下方括号。(来源:https ://bugzilla.mozilla.org/show_bug.cgi?id=1152455#c6 )。因此,我想大部分网络已经开始依赖这种行为,这使得它极不可能改变。
我对 WHATWG URL 标准的解读,至少对于 Web 而言,它可以被视为取代 RFC 3986,它将这种不编码的行为编码[
为]
查询字符串。
编辑:根据评论和其他答案,对 WHATWG URL 标准的更正确解读是未编码的[
/无效,但在接收/解析时也应该被容忍,并且一旦以这种方式解析,甚至应该在不编码的情况下重新序列化.]
理想情况下,我真的很想评论Ethan 的回答,但没有足够的声誉来做这件事。
我不确定这里是否引用了 WHATWG URL 标准的相关部分。我认为正确的部分可能在有效URL-query string的定义中,它描述为由URL 单元组成,这些单元本身由URL 代码点和百分比编码字节组成。方括号列在 URL 代码点内,因此属于百分比编码字节类别。
因此,在回答原始问题时,URL 的查询部分中的多维数组语法(即使用方括号表示数组索引)是有效的,前提是方括号是百分比编码的(如 %5B 表示 [ 和 %5D 表示 ] )。
我的理解是方括号无论如何都不是一等公民。这是报价: https ://www.rfc-editor.org/rfc/rfc1738
其他字符是不安全的,因为已知网关和其他传输代理有时会修改这些字符。这些字符是“{”、“}”、“|”、“”、“^”、“~”、“[”、“]”和“`”。
当我必须传递一个数组时,我总是很想进行那种查询,但我避开了它。原因是:
您有几个选项可以传递数组:
如果您确定您使用的语言,您可以(安全地)选择您拥有的那种查询字符串(只是您还需要 %-encode []
)。