在附加查询字符串时始终跳过斜杠是否安全?
那我可以用
http://example.com?querystring
代替:
http://example.com/?querystring
?我使用过的所有Web主机都支持此功能,但是可以安全地假设所有服务器环境都支持此方法吗?是标准的吗?
Answers:
否。跳过斜线是不正确的。它可能适用于现代浏览器:但是,这并不正确。
请参阅RFC1738-URL和 RFC2396-URI。
符合RFC1738的格式(我在这里已排除了模式格式):
// <用户>:<密码> @ <主机>:<端口> / <URL路径>
并继续指出:
...主机(或端口)与url路径之间的“ /”不属于url路径。
在这种情况下,“?” 是url-path的一部分
...取决于所使用的方案,其解释方式也一样。
还要注意,根据规范,完全省略“ / url-path”是完全有效的-注意,在这种情况下,“ /”已明确包含在内。
因此,“ foo.com?bar”无效,因为url路径前没有“ /”。
就现代规范而言,是的,可以跳过斜线,这与此处公认的答案相反。
尽管公认的答案正确引用了RFC 1738(发布于20年前!),但它错误地声称RFC 2396(发布于1998年)需要使用斜杠,而忽略了这两个规范,而RFC 3986则已弃用了这些规范。 2005年(距编写接受的答案还差几年),最近又由WhatWG URL Standard提出,两者都允许省略斜线。
让我们依次从最早到最新考虑以下每个规范:
隐需要由包括斜杠指定它可以被忽略,如果该URL既不包含路径,也没有查询字符串(称为searchpart
,在这里)。下面的粗体是我的:
HTTP URL的形式为:
http://<host>:<port>/<path>?<searchpart>
其中
<host>
和<port>
如第3.1节所述。如果<port>
省略:,则端口默认为80。不允许使用用户名或密码。<path>
是HTTP选择器,并且<searchpart>
是查询字符串。和以及其前面的“?”<path>
一样,是可选的<searchpart>
。如果<path>
也不<searchpart>
存在,则也可以省略“ /”。
在这里可以省略斜线。该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中的第一个问号(在任何位置)都标记了查询字符串的开头,因此该规范进行了务实的更新以符合实际情况。
同样,可以省略斜杠。该规范由话说,“路径”是必需的,它包含一个机构(主机)每一个URI,而且路径必须表示这要么以斜杠或包括没有字符:
通用URI语法由组件的层次结构序列组成,称为方案,权限,路径,查询和片段。
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty
尽管路径可能为空(无字符),但方案和路径组件是必需的。如果存在权限,则路径必须为空或以斜杠(“ /”)开头。
为了完整起见,请注意,path-abempty
稍后定义如下:
path-abempty = *( "/" segment )
这确实允许它不包含任何字符。
同样,省略斜线是可以接受的,尽管这次我们没有要看的BNF,而是需要阅读大量散文。
第4.3节告诉我们:
一个绝对URL字符串必须是下列之一
- 一个URL的方案字符串是一个ASCII不区分大小写的匹配项特别计划,而不是一个ASCII不区分大小写的“匹配
file
”,其次是“:
”和计划后相对特殊的URL字符串- 一个URL的方案串是不是一个ASCII不区分大小写的匹配项特别计划,其次是“:”和一个相对URL字符串
- 一个URL的方案字符串是一个ASCII不区分大小写的“文件”,之后的比赛“:”和方案相对文件的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。但就规范而言,跳过斜线是完全合法的。
?
在地址栏中的之前添加一个斜杠:例如,加载页面时,https://stackoverflow.com?test已替换为https://stackoverflow.com/?test。我可以防止这种行为吗?
研究此问题后,我在找到的答案中添加了更多信息:
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。
总之,它应该可以工作,但是在某些情况下会失败。
它是不是安全的假设。Web服务器和独立的Web应用程序通常检查请求中提供的URL,但不能保证它们将被视为/abc
等于/abc/
。Web服务器和独立的Web应用程序可以使用从URL收集的信息来做任何喜欢的事情,而这不一定是您期望的。您将必须找出有关特定URL的约定。
当然,请注意,大多数Web服务器和Web应用程序框架都尽力接受各种输入并进行适当处理。因此,在大多数情况下,Web服务器或独立的Web应用程序将把/abc
等于/abc/
。但是请记住,由于服务器可以对路径执行任何操作,因此这只是一个泛泛的观察,可能会有许多异常。
Location
在请求中添加标头,则会将其发送给客户端,客户端将负责正确了解您的原始意图。客户端将尝试通过在根位置添加斜杠来“修复”您的URL(如果这样做的话)。/
无论您是否输入URL栏,任何浏览器发送的所有请求(无论是否现代)都将始终以开头。