在HTTP URL的path部分中,斜杠(“/”)等同于编码的斜杠(“%2F”)

我有一个网站,不同的URL的path部分(而不是查询string)中的“/”和“%2F”。 根据RFC或现实世界,这是一件坏事吗?

我问,因为我一直使用我正在使用的Web框架(Ruby on Rails)以及下面的层(Passenger,Apache,例如,我必须为Apache启用“ALLOW_ENCODED_SLASHES”)时遇到一些小惊喜。 我现在倾向于彻底摆脱编码的斜杠,但是我不知道是否应该提交错误报告,在那里我看到涉及编码斜杠的奇怪行为。

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

:controller/:foo/:bar 

其中:foo类似于可以包含斜杠的path。 我认为最简单的事情就是只要URL转义foo所以斜杠被路由机制忽略。 现在我有疑问了,很明显,这个框架并不是真的支持这个,但根据RFC,这样做是错误的吗?

以下是我收集的一些信息:

RFC 1738(URL):

当一个八位字节由一个字符表示并且被编码时,通常一个URL具有相同的解释。 但是,对于保留字符而言,这不是真的:对为特定scheme保留的字符进行编码可能会改变URL的语义。

RFC 2396(URI):

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

(在这里转义意味着除了编码保留字符之外的东西吗?)

RFC 2616(HTTP / 1.1):

除“保留”和“不安全”集以外的字符(见RFC 2396 [42])等同于其“”HEX HEX“%”编码。

还有Rails的这个错误报告 ,他们似乎期望编码的斜线行为不同:

对,我期望不同的结果,因为他们指着不同的资源。

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

从RFC中可以清楚的看到,原始编码和未编码的字符是相同的,但是保留字符的故事是什么?

从你收集的数据来看,我倾向于说,在uri中编码的“/”意味着在application / cgi级别再次被视为“/”。

也就是说,如果你使用的是mod_rewrite apache,那么它就不会匹配模式,这个模式会使用带有编码的斜线的URI。 但是,一旦调用了适当的module / cgi / …来处理请求,就需要进行解码,例如,检索包含斜线的参数作为URI的第一个组件。

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

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

我也有一个网站,有urlencoded字符众多的url。 我发现许多Web API(包括谷歌网站pipe理员工具和几个Drupal模块)都是通过urlencoded字符来转换的。 许多API在其进程的某个时刻自动解码URL,然后将结果用作URL或HTML。 当我发现其中一个问题时,我通常会对该API的结果(将%2f转换为%252f)进行双重编码。 但是,这会打破其他不需要双重编码的API,所以这不是一个通用的解决scheme。

就我个人而言,我正在摆脱尽可能多的特殊字符在我的url。

此外,我在我的url中使用不依赖于urldecoding的ID号码:

example.com/blog/my-amazing-blog%2fstory/yesterday

变为:

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

在这种情况下,我的代码只使用12354来查找文章,其余的URL被我的系统忽略(但仍然用于search引擎优化)。此外,这个数字应该出现在未使用的URL组件之前。 这样,即使%2f得到解码不正确,该url仍然可以正常工作。

此外,请务必使用规范标签,以确保url错误不会翻译成重复的内容。

如果您使用Tomcat,请在VM属性中添加“-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH = true”。

https://tomcat.apache.org/tomcat-7.0-doc/config/systemprops.html#Security

根据最初的W3Cbuild议 , %2F vs /的故事是“削减”必须包含一个等级结构“

例2

URIs

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

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

是不相同的,因为在第二种情况下,编码的斜线不具有层次的意义。