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)检测字符串的编码?我已经检查了请求标头,它们似乎没有任何帮助.
感谢您的所有评论和回答!在发布问题后,我自己做了一些挖掘,并想在这里写下来作为参考。如果这个答案有误,请告诉我。
\n跳到最后直接进入结论。
\n从关于国际字符和字符编码的 JETTY 文档,\n从“URL 中的国际字符”部分,我找到了这些\n段落:
\n\n\n由于缺乏标准,不同的浏览器对所使用的字符编码采取了不同的方法。有些使用页面的编码,有些使用 UTF-8。各个标准机构起草了一些草案,建议 UTF-8 将成为标准编码。旧版本的 jetty(例如 4.0.x 系列)使用 UTF-8 作为默认值,以期采用标准。由于标准尚未出台,jetty-4.1.x 恢复为默认编码 ISO-8859-1。
\nW3C 组织的 HTML 标准现在建议使用 UTF-8:http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars,因此 jetty-6 系列使用默认为 UTF-8。
\n
在链接的 HTML 4.0 规范中,确实建议客户端在对非 ASCII 字符进行百分比编码之前先将其编码为 UTF-8,因此我们知道自 HTML 4.0 以来,W3C 就已提出了这一建议。
\n页面上使用的示例是这样的:
\n<A href="http://foo.org/H\xc3\xa5kon">...</A>\nRun Code Online (Sandbox Code Playgroud)\n虽然它后来指出相同的编码应该应用于片段部分,但它并没有说它是否也应用于查询字符串。
\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 格式发送所有内容,因此无需担心。
\nWindows 中的 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:
\nhttp://localhost/test/\xc3\xbc/\xc3\xa4/index.php?ch\xc3\xa4r=\xc3\xbc\nRun Code Online (Sandbox Code Playgroud)\n查询字符串被编码为 ISO-8859-1,但“路径”部分被编码为 UTF-8:
\nhttp://localhost//test/%C3%BC/%C3%A4/index.php?ch%E4r=%FC\nRun Code Online (Sandbox Code Playgroud)\n另请注意,根据这篇博客文章,Firefox 3.0\n将片中字符 \xe3\x82\xa2 转换为ア百分号编码之前的\nit。当我尝试在 Firefox 3.6.13 的查询字符串和路径中执行此操作时,katanaka 字符会正确编码为 UTF-8。
歌剧
\nMac 上的 Opera 10.10 将 URI 的查询字符串部分编码为\nISO-8859-1,即使 Mac OS X 的默认编码为\nUTF-8。“路径”部分被编码为 UTF-8,就像 Firefox 一样。
\n如果您尝试在查询字符串中输入希腊字母 \xce\xb1,它会以问号的形式发送。
\nWindows XP 中的 Opera 11.51 也表现出相同的行为。
\n苹果浏览器
\nMac 上的 Safari 5.1 始终以 UTF-8 形式发送所有内容。\nWindows 上的 Safari 5.1 也表现出相同的行为。
\n铬合金
\nWindows 上的版本 13 将查询字符串和路径编码为\nUTF-8。我在 Mac 上没有 Chrome,但似乎可以安全地假设\nChrome 总是发送 UTF-8,就像 Safari 一样。
\nIE浏览器
\n免责声明:我使用 IECollection 在一台计算机上安装多个版本的 IE,因此这可能不是 IE 的自然行为(任何人都可以确认这一点吗?)。
\nWindows XP 中的 IE 6、7 和 8 将 URI 的“路径”部分正确编码为\nUTF-8。不过,在查询中输入的变音符号和希腊字母\n字符串不会进行百分比编码。在地址栏输入的查询字符串似乎是以 ISO-8859-1 格式发送的,查询字符串中的希腊字母 alpha \'\xce\xb1\' 被音译为 \'a\'。
\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另请参阅bobince 的这个很好的答案。
\n此后,解析 URI 时就不会有任何问题了。如果编码不是 UTF-8,那么这是一个错误的请求,您可以使用 404 或 400 页面进行响应。
\n| 归档时间: |
|
| 查看次数: |
1297 次 |
| 最近记录: |