可以在查询字符串之前跳过斜杠吗?
Posted
技术标签:
【中文标题】可以在查询字符串之前跳过斜杠吗?【英文标题】:OK to skip slash before query string? 【发布时间】:2010-12-09 16:16:44 【问题描述】:在附加查询字符串时总是跳过尾部斜杠是否安全?
也就是说,我可以用吗
http://example.com?querystring
代替:
http://example.com/?querystring
?我使用过的所有虚拟主机都支持此方法,但假设所有服务器环境都支持此方法是否安全?标准吗?
【问题讨论】:
这与服务器无关。如果您在请求中添加Location
标头,它会将其发送给客户端,客户端将负责正确理解您的原始意图。客户端将尝试通过在根位置添加斜杠来“修复”您的 URL,如果这是它的设计目的。无论您在 URL 栏中输入什么内容,任何浏览器(无论是否现代)发送的所有请求都将始终以 /
开头。
【参考方案1】:
按照现代规范,是的,允许跳过斜线,这与 accepted answer 此处声称的相反。
虽然接受的答案正确引用了 RFC 1738(20 多年前发布!),但它错误地声称 RFC 2396(1998 年发布)需要斜杠,并忽略了 两个 这两个规范都有反过来又被RFC 3986 淘汰,2005 年发布(距离接受的答案还早几年),最近又被WhatWG URL Standard 淘汰,两者都允许省略斜杠。
让我们依次考虑这些规范,从最早到最新:
RFC 1738: Uniform Resource Locators (URL)(1994年发布)
隐式要求specifying that it may be omitted if the URL contains neither a path nor a query string 包含斜线(此处称为searchpart
)。下面的粗体字是我的:
HTTP URL 采用以下形式:
http://<host>:<port>/<path>?<searchpart>
其中
<host>
和<port>
如Section 3.1 中所述。如果:<port>
省略,端口默认为80。没有用户名和密码 允许。<path>
是 HTTP 选择器,<searchpart>
是查询 细绳。<path>
是可选的,<searchpart>
和它的 前面的“?”。 如果<path>
和<searchpart>
都不存在,则“/” 也可以省略。
RFC 2396: Uniform Resource Identifiers (URI): Generic Syntax(1998 年发布;“更新”RFC 1738)
这里可以省略斜线。该 RFC 将一些在方案后没有双斜杠的奇怪 URL 语法合法化,但如果我们忽略这些(它们是在规范的 BNF 中带有 opaque_part
的那些)并坚持使用包含host,然后我们发现absoluteURI
是这样定义的……
absoluteURI = scheme ":" ( hier_part | opaque_part )
hier_part
看起来像这样:
hier_part = ( net_path | abs_path ) [ "?" query ]
net_path
看起来像这样:
net_path = "//" authority [ abs_path ]
abs_path
又被定义为以斜杠开头。请注意,abs_path
在上述语法中是可选 - 这意味着scheme://authority?query
形式的 URL 是完全合法的。
附录G.2. Modifications from both RFC 1738 and RFC 1808暗示了这一变化的动机:
问号“?”字符已从允许的集合中删除 权限组件中用户信息的字符,因为测试 表明许多应用程序将其视为保留用于分离 来自 URI 其余部分的查询组件。
换句话说 - 现实世界中的代码假设 URL 中的第一个问号,任何地方,都标记了查询字符串的开头,因此规范被务实地更新以与现实保持一致。
RFC 3986: Uniform Resource Identifier (URI): Generic Syntax(2005 年发布;“过时”RFC 2396)
同样,可以省略斜线。规范通过说每个包含权限(主机)的 URI 中都需要一个“路径”来表达这一点,并且该路径必须要么以斜杠开头或由没有字符:
3. Syntax Components
通用 URI 语法由一个分层序列组成 称为方案、权限、路径、查询和 片段。
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty
scheme 和 path 组件是必需的,尽管路径可能是 空(无字符)。当权威存在时,路径必须 可以为空或以斜杠(“/”)字符开头。
为了完整起见,请注意path-abempty
稍后是这样定义的:
path-abempty = *( "/" segment )
这确实允许它不包含任何字符。
URL Standard 来自 WhatWG(积极维护的生活标准,于 2012 年首次创建,目标是淘汰 RFC 3986)
同样,省略斜线是可以接受的,尽管这次我们没有 BNF 可看,而是需要阅读大量散文。
Section 4.3 告诉我们:
absolute-URL string 必须是以下之一
URL-scheme string 是 ASCII case-insensitive 匹配 special scheme 而不是 ASCII case-insensitive 匹配 "file
",后跟 ":
" 和 scheme-relative-special-URL string URL-scheme string 不是ASCII case-insensitive 匹配special scheme,后跟“:”和relative-URL string URL-scheme string 是 ASCII case-insensitive 匹配“文件”,后跟“:”和 scheme-relative-file-URL string任何可选的后跟“?”和一个 URL 查询字符串。
由于 HTTP 和 HTTPS 是 special schemes,任何 HTTP 或 HTTPS URL 都必须满足这三个选项中的第一个 - 即 http:
或 https:
后跟 scheme-relative-special-URL string,其中:
必须是“
//
”,后跟valid host string,后跟可选的“:
”和URL-port string,后跟可选的path-absolute-URL string。
path-absolute-URL string 被定义为以斜杠开头,但在上面的绝对 URL 字符串的定义中是显式可选的;因此,允许从主机直接访问“?
”和查询字符串,因此像http://example.com?query
这样的 URL 是合法的。
当然,这些都不能保证每个 Web 服务器或 HTTP 库都会接受此类 URL,也不会将它们视为在语义上等同于包含斜杠的 URL。但就 spec 而言,跳过斜线是完全合法的。
【讨论】:
(不幸的是)浏览器(例如Chrome),在地址栏中的?
之前添加一个斜杠:例如在加载页面时将https://***.com?test替换为https://***.com/?test。我可以防止这种行为吗?
页面是目录还是文件有关系吗?从 SEO 的角度来看?【参考方案2】:
没有。跳过斜线是不正确的。它可能适用于现代浏览器:但是,这并不正确。
请参阅RFC1738 - URL 和 RFC2396 - URI.
按照 RFC1738 的格式(我在这里排除了架构格式):
//
: @ : /
它继续指出:
...主机(或端口)和 url-path 之间的“/”不是 url-path 的一部分。
在这种情况下,“?”是 url-path 的一部分
...取决于所使用的方案,以及它的解释方式。
另请注意,根据规范,省略“/url-path”是完全有效的——注意“/”已明确包含在这种情况下。
因此,“foo.com?bar”是无效的,因为 url-path 之前没有“/”。
【讨论】:
-1;这个答案几乎是完全错误的。它引用了 1990 年代的规范,这些规范在编写此答案时已经过时了,虽然它正确地将 RFC 1738 解释为需要斜杠,但它引用了 RFC 2396 却没有注意到 RFC 2396 明确允许省略斜杠。请参阅 my answer 以详细分析这两个规范的内容,以及更多的 RFC 3986 和 WhatWG URL Living Standard,两者都允许省略斜杠。 顺便说一句,各位,please,please 引用 IETF 的 RFC 的 html 版本(例如tools.ietf.org/html/rfc1738),而不是文本(例如ietf.org/rfc/rfc1738.txt)。除了更漂亮和更容易浏览之外,它们还包含一个标题栏,清楚地标记规范是否已过时。我现在已经编辑了这个答案以引用 HTML 版本,但是如果这里的回答者首先阅读(并链接到)它们,那么任何人都不会需要 7 年的时间才能注意到这个答案是引用自 2005 年以来已过时的规范。 让我举一个反例。 YouTube 链接在“?”之前没有“/”。实际上,OP 是在询问服务器是否将它们视为等效,而不是关于浏览器。无论如何,请考虑使用更新后的规范更新您的答案。 @KevinLee 恐怕没有什么意义建议作者更新这个答案 - 他们的帐户不再存在。 @MarkAmery 谢谢your answer。不幸的是,这个错误的答案仍然是公认的答案。【参考方案3】:在研究此问题后发现的更多信息添加到已接受的答案中:
https://www.rfc-editor.org/rfc/rfc2396
权限组件以双斜杠“//”开头,并以下一个斜杠“/”、问号“?”或 URI 结尾终止。在权限组件中,保留字符“;”、“:”、“@”、“?”和“/”
基于此声明,问号应指示权限组件的结尾,带或不带斜线。
https://www.rfc-editor.org/rfc/rfc1738(标签被替换)
path 是可选的,searchpart 及其前面的“?”也是如此。如果 path 和 searchpart 都不存在,“/”也可以省略。
但是,此语句表示,只有在未预设路径和搜索部分时,才能省略尾部斜杠。
在现实世界中,我以前可以在查询值之前省略尾部斜杠,但最近发现了一种情况。如果您有类似 http://my.domain.com?do=something 的查询,并且您在 Internet Explorer 中查看 html 页面,则该链接已被 IE固定。如果您随后单击“文件”、“发送”、“通过电子邮件发送页面...”,则会将链接添加到格式无效的电子邮件中。问题因查询值的内容而异,但我们能够创建无效的 URL。
总而言之,它应该工作,但在极端情况下会失败。
【讨论】:
另一个极端情况:当我使用 AJAX 从 REST API 请求数据时,我得到了一堆 301 重定向......直到我使用了一个斜杠(在查询参数之前)。我以前从未见过这种 URL 格式,但添加的斜线意味着我不再获得那些 301 重定向。在这种情况下,URL 模式是 server.dsl/endpoint/id/?q=something @Majorie,听起来您调用的 REST API 没有正确处理您的请求结构,而是将 id 作为控制器映射而不是端点处理。无论哪种方式,它都是基于看似可选的 URL 结构的潜在行为变化的一个很好的例子。 这个答案(与接受的答案不同)正确解释了 RFC 2396 并指出 RFC 1738 需要斜杠,而 RFC 2396 不需要。但是(就像公认的答案一样)它仍然没有注意到 RFC 2396 是一个早已过时的 RFC,在 2005 年 1 月被 RFC 3986 取代,这比写这个答案早了将近十年。【参考方案4】:假设这一点是不安全的。 Web 服务器和自包含 Web 应用程序通常会检查请求中提供的 URL,但不能保证它们会将 /abc
视为等于 /abc/
。 Web 服务器和独立的 Web 应用程序可以使用从 URL 收集的信息为所欲为,这不一定是您所期望的。您将必须找出所讨论的特定 URL 的约定。
当然,请注意,大多数 Web 服务器和 Web 应用程序框架都努力接受各种输入并适当地处理它们。因此,在大多数情况下,Web 服务器或自包含 Web 应用程序会将 /abc
视为等于 /abc/
。但是请记住,因为服务器可以对路径做任何它喜欢做的事情,这只是一个普通的观察,可能有很多例外。
【讨论】:
不可能(使用浏览器)向 Web 服务器触发这种请求。所有 HTTP 请求都必须以 / 开头,并且没有浏览器会出错。即使 Google Chrome 会接受该 URL,它也会始终向服务器发出以 / 开头的请求。 @MilosIvanovic 重点在于斜杠。我不认为他在争论开头/。【参考方案5】:可以在两者之间使用查询字符串,下面也是示例
/rest/mainfolder/subfolder?jsonFormat=stream&/value1/value2
【讨论】:
以上是关于可以在查询字符串之前跳过斜杠吗?的主要内容,如果未能解决你的问题,请参考以下文章