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


74

在附加查询字符串时始终跳过斜杠是否安全?

那我可以用

http://example.com?querystring

代替:

http://example.com/?querystring

?我使用过的所有Web主机都支持此功能,但是可以安全地假设所有服务器环境都支持此方法吗?是标准的吗?


这与服务器无关。如果Location在请求中添加标头,则会将其发送给客户端,客户端将负责正确了解您的原始意图。客户端将尝试通过在根位置添加斜杠来“修复”您的URL(如果这样做的话)。/无论您是否输入URL栏,任何浏览器发送的所有请求(无论是否现代)都将始终以开头。
米洛斯·伊万诺维奇

Answers:


44

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

请参阅RFC1738-URLRFC2396-URI

符合RFC1738的格式(我在这里已排除了模式格式):

// <用户>:<密码> @ <主机>:<端口> / <URL路径>

并继续指出:

...主机(或端口)与url路径之间的“ /”不属于url路径。

在这种情况下,“?” 是url-path的一部分

...取决于所使用的方案,其解释方式也一样。

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

因此,“ foo.com?bar”无效,因为url路径前没有“ /”。


12
-1; 这个答案几乎是完全错误的。它援引了1990年代写此答案时已经过时的规范,尽管它正确地将RFC 1738解释为要求使用斜杠,但它引用RFC 2396却没有注意到RFC 2396明确允许省略斜杠。请参阅我的答案,以详细分析这两个规范所说的内容,以及更多的RFC 3986和WhatWG URL Living Standard,这两个标准都允许省略斜线。
Mark Amery

2
顺便说一句,人,请,举IETF的RFC文档的HTML版本(如tools.ietf.org/html/rfc1738),而不是文本的人(如ietf.org/rfc/rfc1738.txt)。除了美观和易于浏览之外,它们还包含一个标题栏,可以清楚地标记该规范是否已过时。我已经编辑了此答案以引用HTML版本,但是如果此处的答题者首先阅读(并链接到它们),那么任何人都不可能花7年的时间才能注意到此答案是引用自2005
。– Mark Amery

让我只说一个反例。YouTube链接的“?”前没有“ /”。实际上,OP询问的是服务器是否将它们视为等同的对象,而不是浏览器。无论如何,请考虑使用更新的规范来更新您的答案。
凯文·李

@KevinLee恐怕没有太多迹象表明作者更新了此答案-他们的帐户已不存在。
马克·阿默里

@MarkAmery谢谢您的回答。不幸的是,这个错误的答案仍然是公认的答案。
leosteffen

80

就现代规范而言,是的,可以跳过斜线,这与此处公认的答案相反。

尽管公认的答案正确引用了RFC 1738(发布于20年前!),但它错误地声称RFC 2396(发布于1998年)需要使用斜杠,而忽略了这两个规范,而RFC 3986则已弃用了这些规范。 2005年(距编写接受的答案还差几年),最近又由WhatWG URL Standard提出,两者都允许省略斜线。

让我们依次从最早到最新考虑以下每个规范:


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

隐需要由包括斜杠指定它可以被忽略,如果该URL既不包含路径,也没有查询字符串(称为searchpart,在这里)。下面的粗体是我的:

HTTP URL的形式为:

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

其中<host><port>第3.1节所述。如果<port> 省略:,则端口默认为80。不允许使用用户名或密码。 <path>是HTTP选择器,并且<searchpart>是查询字符串。和以及其前面的“?”<path>一样,是可选的<searchpart>如果<path>也不<searchpart>存在,则也可以省略“ /”。


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

在这里可以省略斜线。该RFC合法化了一些在方案后没有双斜杠的怪异URL语法,但是如果我们忽略这些语法(它们opaque_part在规范的BNF中带有),并坚持使用包含主机的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可选的-表示该形式的URLscheme://authority?query完全合法。

附录G.2暗示了进行此更改的动机对RFC 1738和RFC 1808的修改

问号“?” 已从授权组件中userinfo的允许字符集中删除了该字符,因为测试表明许多应用程序将其视为保留的,用于将查询组件与URI的其余部分分开。

换句话说-现实世界中的代码假定URL中的第一个问号(在任何位置)都标记了查询字符串的开头,因此该规范进行了务实的更新以符合实际情况。


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

同样,可以省略斜杠。该规范由话说,“路径”是必需的,它包含一个机构(主机)每一个URI,而且路径必须表示这要么以斜杠包括没有字符:

3.语法组成

通用URI语法由组件的层次结构序列组成,称为方案,权限,路径,查询和片段。

URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]

hier-part   = "//" authority path-abempty
            / path-absolute
            / path-rootless
            / path-empty

尽管路径可能为空(无字符),但方案和路径组件是必需的。如果存在权限,则路径必须为空或以斜杠(“ /”)开头。

为了完整起见,请注意,path-abempty稍后定义如下:

path-abempty  = *( "/" segment )

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


WhatWG的URL标准(一种主动维护的生活标准,于2012年首次创建,旨在淘汰RFC 3986)

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

第4.3节告诉我们:

一个绝对URL字符串必须是下列之一

任何可选的后跟“?” 和一个URL查询字符串。

由于HTTP和HTTPS是特殊方案,因此任何HTTP或HTTPS URL必须满足这三个选项中的第一个-即,http:https:后跟一个scheme-relative-special-URL字符串,该字符串

必须为“ //”,后跟有效的主机字符串,并可选地后跟“ :”和URL端口字符串,并可选地后跟path-absolute-URL字符串

路径绝对URL字符串被定义为开始以斜线,但是在绝对-URL字符串以上的定义明确可选的; 因此,可以直接从主机转到“ ?”并查询字符串,因此类似URLhttp://example.com?query都是合法的。


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


1
(不幸的是)浏览器(例如Chrome)?在地址栏中的之前添加一个斜杠:例如,加载页面时,https//stackoverflow.com?test已替换为https://stackoverflow.com/?test。我可以防止这种行为吗?
Alex Vang

5

研究此问题后,我在找到的答案中添加了更多信息:

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

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

根据此陈述,问号应指示授权组成部分的结尾(带有或不带有斜杠)。

http://tools.ietf.org/html/rfc1738(已替换标签)

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

但是,该语句说,只有在未预先设置路径和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
Marjorie Roswell

1
@Majorie,听起来像您正在调用的REST API未正确处理您的请求结构,并且将id作为控制器映射而不是端点进行处理。无论哪种方式,它都是基于似乎是可选URL结构的潜在行为更改的一个很好的例子。
克里斯·波特

此答案(与接受的答案不同)正确地解释了RFC 2396,并指出RFC 1738要求使用斜杠,而RFC 2396则不需要。但是(仍然像接受的答案一样),它仍然没有注意到RFC 2396是一个已过时的RFC,在撰写此答案将近十年之前,它于2005年1月被RFC 3986取代。
Mark Amery

4

它是不是安全的假设。Web服务器和独立的Web应用程序通常检查请求中提供的URL,但不能保证它们将被视为/abc等于/abc/。Web服务器和独立的Web应用程序可以使用从URL收集的信息来做任何喜欢的事情,而这不一定是您期望的。您将必须找出有关特定URL的约定。

当然,请注意,大多数Web服务器和Web应用程序框架都尽力接受各种输入并进行适当处理。因此,在大多数情况下,Web服务器或独立的Web应用程序将把/abc等于/abc/。但是请记住,由于服务器可以对路径执行任何操作,因此这只是一个泛泛的观察,可能会有许多异常。


不可能通过浏览器向Web服务器发出这种请求。所有HTTP请求都必须以/开头,并且没有浏览器会出错。即使Google Chrome浏览器会接受该URL,也会始终以/开头向服务器发出请求。
米洛斯·伊凡诺维奇

@MilosIvanovic关键是关于斜杠。我不认为他是关于/的争论。
凯文·李
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.