是斜杠(“ /”)等同于HTTP URL路径部分中的编码斜杠(“%2F”)


74

我有一个站点在URL的路径部分(而不是查询字符串)中以不同的方式对待“ /”和“%2F”。根据RFC还是现实世界,这是一件坏事吗?

我问是因为我对正在使用的Web框架(Ruby on Rails)以及它下面的层(Passenger,Apache,例如,我必须为Apache启用“ ALLOW_ENCODED_SLASHES”)感到惊讶。我现在倾向于完全摆脱编码的斜杠,但是我想知道是否应该在我看到涉及编码的斜杠的怪异行为时提交错误报告。

至于为什么我首先使用编码的斜杠,基本上我有这样的路由:

:controller/:foo/:bar

:foo是类似路径的内容,可以包含斜杠。我认为最直接的方法就是仅对URL进行转义,foo从而使斜线被路由机制忽略。现在,我对此表示怀疑,很明显,这些框架并不真正支持此功能,但是根据RFC的说法,这样做是错误的吗?

这是我收集的一些信息:

RFC 1738(URL):

通常,当八位字节由字符表示并进行编码时,URL具有相同的解释。但是,对于保留字符而言并非如此:对为特定方案保留的字符进行编码可能会更改URL的语义。

RFC 2396(URI):

这些字符被称为“保留”,因为它们在URI组件中的使用仅限于其保留目的。如果URI组件的数据将与保留用途冲突,则必须在形成URI之前转义冲突的数据。

(这里的转义除了编码保留字符之外还意味着其他吗?)

RFC 2616(HTTP / 1.1):

除“保留”和“不安全”集中的字符以外的其他字符(请参阅RFC 2396 [42])等效于其““%” HEX HEX“编码。

还有一个针对Rails的错误报告,他们似乎希望编码的斜杠的行为有所不同:

是的,我期望会有不同的结果,因为它们指向的是不同的资源。

它在根目录中查找文字文件“ foo / bar”。非转义版本正在目录foo中查找文件栏。

从RFC可以明显看出,原始字符与编码字符等效于未保留字符,但是保留字符的含义是什么?



使用前端控制器$ _GET和$ _REQUEST的PHP用户已被urldecoded。这可能会导致斜杠出现问题,因为您将无法分辨出什么是斜杠以及什么是%2F。如果您绝对需要查看发送的请求,请查看$ _SERVER ['REQUEST_URI']。另请参阅urldecode()@php.net
Patrick James McDougle,2014年

Answers:


34

从您收集的数据来看,我倾向于说在uri中编码的“ /”在应用程序/ cgi级别上又被视为“ /”。

就是说,例如,如果您将apache与一起使用mod_rewrite,则它将与期望其中包含编码斜杠的URI斜杠的模式不匹配。但是,一旦调用了适当的module / cgi / ...来处理该请求,就由它来进行解码,例如检索包含斜杠的参数作为URI的第一部分。

如果您的应用程序随后使用此数据来检索文件(其文件名包含斜杠),那可能是一件坏事。

总而言之,我发现看到“ /”或“%2F”中行为的差异是完全正常的,因为它们的解释将在不同的级别进行。


1
这也是我一直在想的。不幸的是,在现实世界中似乎没有太多人支持这样做。我现在将继续工作,但是如果我要重新开始,我将尝试使用另一种转义机制。
user85509

@ user85509我想知道是否应该在我看到涉及编码斜杠的奇怪行为的地方提交错误报告。-请您每次不符合其中明确指出,RFC线观察行为的时间做/一个保留的字符是不同的,以它的百分之编码形式%2F
Piotr Dobrogost

25

%2Fvs的故事/是,根据W3C最初的建议,斜线“必须暗示层次结构”

斜杠(“ /”,ASCII 2F十六进制)保留用于分隔具有分层关系的子字符串。这将启用URI的部分形式。

例子2

URI

http://www.w3.org/albert/bertram/marie-claude

http://www.w3.org/albert/bertram%2Fmarie-claude

不一样,因为在第二种情况下,编码的斜杠不具有层次结构意义。


那查询呢?就像,查询没有层次结构。它们只是变量。W3C建议对此没有解释,这是小问题。
Eksapsy

9

我也有一个网站,其中包含许多带有urlencode字符的网址。我发现许多Web API(包括Google网站站长工具和几个Drupal模块)都超出了urlencoded字符的限制。许多API在其处理过程中的某个时刻会自动解码url,然后将结果用作URL或HTML。当我发现这些问题之一时,通常会对该API的结果进行双重编码(将%2f转换为%252f)。但是,这将破坏其他不期望双重编码的API,因此这不是通用解决方案。

就个人而言,我会在URL中消除尽可能多的特殊字符。

另外,我在URL中使用的ID号不取决于urldecoding:

example.com/blog/my-amazing-blog%2fstory/昨天

变成:

example.com/blog/12354/my-amazing-blog%2fstory/昨天

在这种情况下,我的代码仅使用12354查找文章,而其他URL被系统忽略(但仍用于SEO。)此外,此数字应在未使用的URL组件之前出现。这样,即使%2f解码不正确,该URL仍将起作用。

另外,请确保使用规范标记以确保url错误不会转换为重复的内容。


这种方法对于reddit.com似乎效果很好。
StockB


2

如果:foo其自然形式包含斜杠怎么办?你不会希望它是不是建议试图保持的区别? 它特别指出

与Unix和其他磁盘操作系统文件名约定的相似之处应视为纯属巧合,而不应指示URI应解释为文件名。

如果要建立一个备份程序的在线接口,并希望将该路径表示为URL路径的一部分,则在文件路径中对斜杠进行编码将是有意义的,因为这实际上并不是该路径的一部分。资源-更重要的是路线/backups/2016-07-28content//home/dan/在双斜杠中丢失文件系统的根。在我阅读时,转义斜线是区分的合适方法。


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.