可以在查询字符串之前跳过斜杠吗?

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>

其中&lt;host&gt;&lt;port&gt; 如Section 3.1 中所述。如果:&lt;port&gt; 省略,端口默认为80。没有用户名和密码 允许。 &lt;path&gt; 是 HTTP 选择器,&lt;searchpart&gt; 是查询 细绳。 &lt;path&gt; 是可选的,&lt;searchpart&gt; 和它的 前面的“?”。 如果&lt;path&gt;&lt;searchpart&gt; 都不存在,则“/” 也可以省略。


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,两者都允许省略斜杠。 顺便说一句,各位,pleaseplease 引用 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

【讨论】:

以上是关于可以在查询字符串之前跳过斜杠吗?的主要内容,如果未能解决你的问题,请参考以下文章

包含斜杠的 SQL Server 2012 查询字符串

命名管道名称可以有反斜杠吗?

从查询字符串 Apache 中删除尾部斜杠

在最后一个正斜杠之前删除部分字符串

删除C#变体中的单个反斜杠

Wordpress - 将查询字符串作为基于斜杠的 URL 传递