【问题标题】:$_COOKIE global var encoding$_COOKIE 全局变量编码
【发布时间】:2019-02-14 20:35:15
【问题描述】:

我知道,我不应该使用 ISO-8859-1,但是我有这个网站由我处理,并且不可能迁移所有 PHP/JS/HTML 以使用 UTF-8 而不是 ISO-8859-1 .

我的问题是这样的:这个网站使用encodeURIComponent 将值存储在带有 Javascript 的 cookie 中。例如,在index.html 文件(使用<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />)中有一个<script> 标记,其中包含以下代码:

document.cookie = "xxx=" + encodeURIComponent("não") + ";.....";

cookie 值存储为n%C3%A3o(我在应用程序选项卡中检查了 Chrome 上的开发工具)。尽管 HTML 文件是 ISO,cookie 仍保存为 UTF-8。伟大的!这正是encodeURIComponent 的工作原理,它始终会将其转换为 UTF-8。

当 PHP 页面使用这个 xxx cookie 值来做一些事情时,问题就出现了。由于所有 PHP 文件都保存为 ISO-8859-1,当它尝试访问 $_COOKIE["xxx"] 时,问题开始发生,例如字符被损坏。

显然我必须使用utf8_decode($_COOKIE["xxx"]) 来解决此问题,因为它会获取 cookie 值并将其解析为 ISO-8859-1。

问题是这个网站有数百个 PHP 文件,这些文件到处都使用 cookie。更改所有代码行将需要大量时间 - 我没有,因为我的老板希望今天解决这个问题。

所以我的问题来了:

1) PHP 如何知道 cookie 应该被读取为 UTF-8 并将 UTF-8 编码分配给 $_COOKIE ?当我访问 $_COOKIE 时,它显然已经解码了 cookie 值,因为 %xx 已经解码。我知道你可以说Of course you dumb, cookies are all the time stored as UTF-8.。但这并不总是正确的。

如果在 PHP 文件中(使用 ISO-8859-1 编码保存),我会这样做:

setcookie("xxx","não");

当我检查 cookie(在 Chrome 开发工具 -> 应用程序选项卡中)时,它显示 n%E3o

你看到了吗? n%E3on%C3%A3o 不同。

那么,在解析cookie时,PHP如何知道n%E3o应该被解码为ISO-8859-1,PHP如何知道n%C3%A3o应该被解码为UTF-8呢?

我知道_GET_POST_COOKIE超级全局变量是PHP自动解码的。但是它是如何知道源字符集的,又是如何决定输出哪个字符集的呢?

【问题讨论】:

  • 我会尝试使用 mb_convert_encoding。 php.net/manual/en/function.mb-convert-encoding.php
  • @Alex 这里和utf8_decode()基本一样。这是在正确的上下文中使用此类功能的罕见情况之一 :)
  • 对不起,你是对的。我只是忽略了它。
  • 全局搜索将 encodeURIComponent() 替换为其旧版等效 escape() 可能会达到目的。现有的 cookie 将会丢失,但今天需要解决的这个问题肯定已经发生多年了;-)

标签: php cookies utf-8 iso-8859-1


【解决方案1】:

PHP 对编码并没有真正“了解”太多。在这种情况下,它不需要。 Percent-encoding,用于 cookie 的内容,明确地在编码中性字节级别工作。意思是,编码本身表示原始字节。 %C3%A3 表示两个字节 0xC3A3,这是字符“ã”的 UTF-8 编码。或者,如果您将它们读取为 ISO-8859-1,则它是字符“ã”的编码。所以 PHP 只是将百分比编码解码为原始字节;最终成为什么角色取决于您对它们的解释。 PHP 根本不解释它们,PHP 字符串只是原始字节数组。

相反,PHP 源代码文件中的任何字符串文字只是一个原始字节数组,其内容取决于保存源代码文件的编码。在保存为 ISO-8859-1 的 PHP 文件中,字符串文字 "não" 包含字节 0x6EF16F。以 UTF-8 存储的同一文件包含字节 0x6EC3A36F。在百分比编码中,这些原始字节只是按原样编码。

有关该主题的更多详细信息,请参阅What Every Programmer Absolutely, Positively Needs To Know About Encodings And Character Sets To Work With Text

【讨论】:

  • 好的,但我认为缺少一些东西。在最新版本的 PHP 中,像 htmlentities(和许多其他)这样的函数现在要求您设置字符集,否则 UTF8 将是默认值。然而,setcookie 函数没有通知字符集的选项,并且由于某种原因 PHP 在我发布给您的示例中使用 ISO-8859-1。为什么默认不使用 UTF-8?此外,setcookie 无法知道我的 srstring 的编码,正如您所说,它只是裸字节。
  • 是的,确切地说,它只是原始字节,这就是为什么setcookie 不需要知道它是什么编码。 PHP 字符串是原始文件中的原始字节,但是它被保存了。 setcookie 将原始字节编码为“百分比编码的原始字节”。 PHP 在任何时候都不需要知道编码实际上是什么,因为它不会将字符串视为字符,也不会解释字符或转换编码。
  • htmlentities() 不同,因为它是一个文本操作函数,需要识别例如é 将其转换为 é。 Cookie 函数不需要知道编码,因为它们不会对它做任何事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-03
  • 1970-01-01
  • 1970-01-01
  • 2012-11-19
  • 1970-01-01
  • 2015-06-12
  • 1970-01-01
相关资源
最近更新 更多