确定在查询string之前跳过斜杠?

附加查询string时总是跳过尾部的斜线是否安全?

也就是说,我可以使用

http://example.com?querystring 

代替:

 http://example.com/?querystring 

? 我用过的所有虚拟主机都支持这个function,但假设所有的服务器环境都支持这种方法是安全的吗? 这是标准吗?

不。跳过斜线是不正确的。可能适用于现代浏览器:但是,这并不正确。

请参阅RFC1738 – URL和RFC2396 – URI 。

每个RFC1738的格式(我已经排除了这里的模式格式):

// <用户>:<密码> @ <主机>:<端口> / <URLpath>

而且它还注意到:

主机(或端口)和urlpath之间的“/”不是urlpath的一部分。

在这种情况下,“?” 是其中的URLpath的一部分

取决于所使用的scheme,以及解释的方式。

还要注意,按照规范, 省略 “/ url-path”是完全有效的 – 注意在这种情况下明确包含了“/”。

因此,“foo.com?bar”是无效的,因为在url-path之前没有“/”。

就现代规范而言, 是的 ,可以跳过斜线,与这里所接受的答案相反。 尽pipe接受的答案正确地引用了RFC 1738(20多年前发布的!),但它错误地声称RFC 2396(1998年发布)要求使用斜杠,而忽略这两个规范反过来被RFC 3986废弃, 2005年(在接受答案之前还有好几年的时间)以及最近的WhatWG URL标准 ,两者都允许省略斜线。

从最早到最新,我们再来看看每个规格:


RFC 1738:统一资源定位符(URL) (1994年发布)

如果 URL不包含path和查询string (这里称为searchpart ) ,则隐含地要求包含斜线。 下面的Bolding是我的:

一个HTTP URL的格式如下:

 http://<host>:<port>/<path>?<searchpart> 

其中<host><port>如3.1节所述。 如果省略: <port> ,则端口默认为80.不允许用户名或密码。 <path>是一个HTTPselect器, <searchpart>是一个查询string。 <path>是可选的, <searchpart>及其前面的“?”也是可选的。 如果<path><searchpart>都不存在,那么“/”也可以省略。


RFC 2396:统一资源标识符(URI):通用语法 (1998年发布;“更新”RFC 1738)

这里可以省略斜杠。 这个RFC合法化了一些在scheme之后没有双斜杠的奇怪的URL语法,但是如果我们忽略这些(在规范的BNF中是那些带有opaque_part的)并且坚持包含主机的URL,那么我们发现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暗示了这种变化的动机。 RFC 1738和RFC 1808的修改 :

问号“?” 字符已从权限组件中userinfo的允许字符集中移除,因为testing显示许多应用程序将其视为保留用于将查询组件与URI的其余部分分开。

换句话说,现实世界中的代码假设URL中的第一个问号标记了查询string的开始,因此规范被实际更新以符合实际。


RFC 3986:统一资源标识符(URI):通用语法 (2005年发布;“废止”RFC 2396)

再次,可以省略斜线。 这个规范expression了这一点,它说每个包含一个权限(主机)的URI都需要一个“path”,该path必须以斜杠开头或者不包含任何字符:

3.语法组件

通用URI语法由称为scheme,权威,path,查询和片段的组件的分层序列组成。

 URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty 

path和path组件是必需的,尽pipepath可能是空的(没有字符)。 当授权存在时,path必须为空或以斜杠(“/”)字符开头。

为了完整性,请注意,后面的path-abempty是由以下定义的:

 path-abempty = *( "/" segment ) 

这确实允许它不包含字符。


由WhatWG 标准的url(在主动维护下的生活标准,2012年首次创build,目标是废除RFC 3986)

再次,省略斜线是可以接受的,虽然这次我们没有BNF看,而是需要阅读大量的散文。

4.3节告诉我们:

绝对URLstring必须是以下之一

  • 一个URL-schemestring ,它是一个特殊scheme的ASCII不区分大小写的匹配,而不是ASCII的不区分大小写的“ file ”匹配,后跟“ : ”和一个scheme-relative-special-URLstring
  • 一个URLschemestring ,它不是一个特殊scheme的ASCII不区分大小写的匹配,后跟“:”和一个相对URLstring
  • 一个URL模式string ,它是“file”的ASCII不区分大小写的匹配,后跟“:”和一个scheme-relative-file-URLstring

任何可选的后面跟“?” 和一个URL查询string。

由于HTTP和HTTPS是特殊的scheme ,任何HTTP或HTTPS URL必须满足这三个选项中的第一个 – 即http:https:后跟一个scheme-relative-special-URLstring ,其中:

必须是“ // ”,然后是一个有效的主机string ,可选地后跟“ : ”和一个URL端口string ,可选地后跟一个path绝对URLstring 。

path绝对URLstring被定义为以斜杠开始,但在上面的绝对URLstring的定义中是明确可选的; 因此,允许从主机直接转到“ ? ”和查询string,因此http://example.com?query这样的URL是合法的。


当然,这些都不能保证每个Web服务器或HTTP库都能接受这样的URL,也不会将它们视为在语义上等同于包含斜线的URL。 但就规格而言,跳过斜线是完全合法的。

假设这是不安全的。 Web服务器和自包含的Web应用程序通常会检查请求中提供的URL,但不能保证他们将/abc等同于/abc/ 。 Web服务器和自包含的Web应用程序可以根据从URL中收集的信息做任何他们喜欢的事情 ,而不一定是您所期望的。 您将不得不找出有关特定URL的约定。

请注意,当然,大多数Web服务器和Web应用程序框架都尽力接受各种input并适当地处理它们。 因此,在大多数情况下,Web服务器或自包含的Web应用程序将把/abc等同于/abc/ 。 但请记住,因为服务器可以做任何喜欢的path,这只是一个普遍的观察,可能有许多例外。

在研究这个问题后,我发现了一些更多的信息,

http://tools.ietf.org/html/rfc2396

权限组件前面是一个双斜杠“//”,由下一个斜杠“/”,问号“?”或URI的末尾来终止。 在权限组件中,字符“;”,“:”,“@”,“?”和“/”被保留

基于这个陈述,问号应该表明权威组件的结束,不论是否有斜线。

http://tools.ietf.org/html/rfc1738 (标签取代)

{path}是可选的,{searchpart}及其前面的“?”是可选的。 如果{path}和{searchpart}都不存在,那么“/”也可以省略。

但是,此声明表示,如果path和search部分都未预设,则只能省略尾部斜线。

在现实世界中,我以前能够在查询值之前省略斜线,但是最近发现情况下降了。 如果你有一个像http://my.domain.com?do=something这样的查询,并且你在Internet Explorer中查看一个html页面,那么这个链接就被IE所固定 。 如果您点击“文件”,“发送”,“通过电子邮件发送页面…”,该链接将以无效的格式添加到电子邮件中。 这些问题因查询值的内容而异,但我们能够创build无效的URL。

总之,它应该工作,但在边缘情况下跌倒。