假设解码的百分比编码的URI变成UTF-8是否安全?

ric*_*tie 15 php uri http

RFC 3986声明新的URI方案应该在编码百分比之前首先编码为UTF-8.但是,这不适用于以前的URI版本.

是否可以安全地假设所有多字节,百分比编码的URI在传递之后变成UTF-8编码的字符串urldecode()

例如,如果内容的$_SERVER['REQUEST_URI']百分比编码为:

/b%C3%BCch/w%C3%B6rterb%C3%BCch
Run Code Online (Sandbox Code Playgroud)

我将此字符串传递给后urldecode(),我应该有一个多字节字符串.但是我怎么知道字符串的编码是什么?在上面的例子中,它是UTF-8,但总是这样安全吗?

如果假设这样做是不安全的,有没有办法(除了mb_detect_encoding)检测字符串的编码?我已经检查了请求标头,它们似乎没有任何帮助.

ric*_*tie 3

感谢您的所有评论和回答!在发布问题后,我自己做了一些挖掘,并想在这里写下来作为参考。如果这个答案有误,请告诉我。

\n

跳到最后直接进入结论。

\n

关于国际字符和字符编码的 JETTY 文档,\n从“URL 中的国际字符”部分,我找到了这些\n段落:

\n
\n

由于缺乏标准,不同的浏览器对所使用的字符编码采取了不同的方法。有些使用页面的编码,有些使用 UTF-8。各个标准机构起草了一些草案,建议 UTF-8 将成为标准编码。旧版本的 jetty(例如 4.0.x 系列)使用 UTF-8 作为默认值,以期采用标准。由于标准尚未出台,jetty-4.1.x 恢复为默认编码 ISO-8859-1。

\n

W3C 组织的 HTML 标准现在建议使用 UTF-8:http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars,因此 jetty-6 系列使用默认为 UTF-8。

\n
\n

在链接的 HTML 4.0 规范中,确实建议客户端在对非 ASCII 字符进行百分比编码之前先将其编码为 UTF-8,因此我们知道自 HTML 4.0 以来,W3C 就已提出了这一建议。

\n

页面上使用的示例是这样的:

\n
<A href="http://foo.org/H\xc3\xa5kon">...</A>\n
Run Code Online (Sandbox Code Playgroud)\n

虽然它后来指出相同的编码应该应用于片段部分,但它并没有说它是否也应用于查询字符串。

\n

在浏览器中输入 URL

\n

火狐浏览器

\n

正如 Pekka 已经提到的,基于此链接, Firefox\n 迟至 2007 年才发送 ISO-8859-1 编码的 URI。阅读该链接,\n这似乎是 Firefox < 3.0 的默认行为。我不确定这是否也适用于 Mac OS X 中的 Firefox < 3.0,因为Mac 中的默认编码是 UTF-8

\n

我已经在 Windows XP 中测试了 Firefox 3.6.13,在 Windows 7 和 Mac OS X 中测试了 Firefox 6。Mac 版本以 UTF-8 格式发送所有内容,因此无需担心。

\n

Windows 中的 Firefox 3.6.13 和 6 默认将查询字符串编码为 ISO-8859-1\n,但是当您在查询字符串中键入\nISO-8859-1 中不存在的字符时(\xce\xb1,例如例如),Firefox 3\n将整个查询字符串的编码切换为 UTF-8。我很确定这在以后的版本中也是同样的行为。

\n

在我测试的 Windows 中的 Firefox 3.6.13 和 6 中,URI 的路径部分始终编码为 UTF-8。

\n

如果您在 Windows 中输入 Firefox 3.6/6 的 URL:

\n
http://localhost/test/\xc3\xbc/\xc3\xa4/index.php?ch\xc3\xa4r=\xc3\xbc\n
Run Code Online (Sandbox Code Playgroud)\n

查询字符串被编码为 ISO-8859-1,但“路径”部分被编码为 UTF-8:

\n
http://localhost//test/%C3%BC/%C3%A4/index.php?ch%E4r=%FC\n
Run Code Online (Sandbox Code Playgroud)\n

另请注意,根据这篇博客文章,Firefox 3.0\n将片中字符 \xe3\x82\xa2 转换为&#12450;百分号编码之前的\nit。当我尝试在 Firefox 3.6.13 的查询字符串和路径中执行此操作时,katanaka 字符会正确编码为 UTF-8。

\n

歌剧

\n

Mac 上的 Opera 10.10 将 URI 的查询字符串部分编码为\nISO-8859-1,即使 Mac OS X 的默认编码为\nUTF-8。“路径”部分被编码为 UTF-8,就像 Firefox 一样。

\n

如果您尝试在查询字符串中输入希腊字母 \xce\xb1,它会以问号的形式发送。

\n

Windows XP 中的 Opera 11.51 也表现出相同的行为。

\n

苹果浏览器

\n

Mac 上的 Safari 5.1 始终以 UTF-8 形式发送所有内容。\nWindows 上的 Safari 5.1 也表现出相同的行为。

\n

铬合金

\n

Windows 上的版本 13 将查询字符串和路径编码为\nUTF-8。我在 Mac 上没有 Chrome,但似乎可以安全地假设\nChrome 总是发送 UTF-8,就像 Safari 一样。

\n

IE浏览器

\n

免责声明:我使用 IECollection 在一台计算机上安装多个版本的 IE,因此这可能不是 IE 的自然行为(任何人都可以确认这一点吗?)。

\n

Windows XP 中的 IE 6、7 和 8 将 URI 的“路径”部分正确编码为\nUTF-8。不过,在查询中输入的变音符号和希腊字母\n字符串不会进行百分比编码。在地址栏输入的查询字符串似乎是以 ISO-8859-1 格式发送的,查询字符串中的希腊字母 alpha \'\xce\xb1\' 被音译为 \'a\'。

\n

结论

\n

这是简短且不完整的,我不能保证它的正确性,但 URI 最常见的编码似乎是 ISO-8859-1 和 UTF-8(我不知道东亚人使用什么作为他们的编码)编码,对我来说太详尽了,无法尝试\n找出答案)。

\n

由于它已经是 HTML 4.0 的推荐,我想假设 URI 的“路径”部分始终以 UTF-8 编码是安全的。Firefox 2.0 可能仍然存在,因此您必须检查\n编码是否也是 ISO-8859-1。如果它不是 UTF-8 或 ISO-8859-1,则很可能是一个错误的请求。

\n

理论上不可能正确检测字符串的编码(请参阅此处此处)。您可以猜测,但\n您可能会得到错误的结果。所以不要依赖编码检测。

\n

安全多字节路由

\n

最安全的方法是为整个应用程序选择一种编码(UTF-8 是最安全的选择)。那么你必须:

\n
    \n
  1. 在使用\n构建 URI 之前,请确保所有字符串都以 UTF-8 进行编码。之后对您的 URI\n进行正确的百分比编码。
  2. \n
  3. 确保所有 URL 编码 (GET) 表单都以正确的编码发送\n数据。请参阅Kore Nordmann 撰写的常见问题解答, \n了解有关确保表单发送正确\n编码的更多信息。
  4. \n
\n

另请参阅bobince 的这个很好的答案

\n

此后,解析 URI 时就不会有任何问题了。如果编码不是 UTF-8,那么这是一个错误的请求,您可以使用 404 或 400 页面进行响应。

\n