PHP:POST和GET中的不同字符集

时间:2014-12-11 20:35:17

标签: php string utf-8 character-encoding ascii

我遇到了在PHP中使用GET和POST-Requests时字符集不同的问题。情况如下:

我有一个挪威语字符串。这个字符串当然可以包含挪威字符(即“Ensjøsvingen”)。如果我通过GET参数传递这个字符串,获取它并让它计数,它报告一个13的strlen [这是正确的]。如果我通过POST参数传递此字符串,获取它并让它计数,它会报告一个17的strlen。

当我使用printf将字符串转换为十六进制时,这就是出现的结果:

GET: 45 6e 73 6a c3 b8 73 76 69 6e 67 65 6e

POST: 45 6e 73 6a 26 23 32 34 38 3b 73 76 69 6e 67 65 6e

显然,POST更长。我的想法是它是charset所以我让PHP告诉我,字符串是什么字符集.PHP报告GET-String是UTF-8和ASCII-POST的UT-8的子集)。使用iconv将ASCII转换为UTF-8在strlen中不会改变任何内容。

问题是,我使用该字符串生成SHA1-hash供以后使用(没有关键要避免更改,所以SHA1完全正常),所以我不能使用mb _ * - 函数来获得完全相同的hash,无论字符串是如何传递的。

我如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

我将在下面留下我的原始答案,因为它确实包含了一些过去对我有很大帮助的信息。但是,在取消提供所提供的输出后,两个字符串之间的区别在于POST中的一个字符串是使用HTML实体编码的。两个字符串都是等效的,但是,您需要使用html_entity_decode(在编码参数中提供UTF-8)来获得所需的结果。我之前已经给出了答案,因为直接字节比较可能在此之后仍然失败,原因如下所述。


当PHP接受来自浏览器的输入时,它不会对字符编码执行任何操作。话虽如此,它确实尝试为GET参数取消对它们进行urlencode。根据浏览器如何编码UTF-8字符串,许多字符在UTF-8中具有多个编码。对于完整字符有一种编码,甚至有几种不同的编码,它们使用基本字符并组合变音符号或其他标记来呈现相同的结果。对于Utf-8感知语言,这没有问题,因为字符的所有编码都应该被视为相等,但是,因为PHP甚至没有尝试使用字符编码,所以您可能只是遇到了相同的两种不同的规范化。字符串。

我在这方面遇到的许多问题都是通过使用intl extension's Normalizer来解决的,因此我总是使用一种正常形式或另一种正常形式,而直接字节比较(而不是UTF-8识别字符比较)会产生相同的结果。所有UTF-8字符串都要记住这一点很重要; strlen()和其他不在mb_string扩展名中的PHP字符串函数不能识别多字节,除非你打开重载,因此在使用UTF-8时会给你字节数而不是字符数。

总而言之,在使用UTF-8时使用mb_string函数,您应该有更好的结果或查看UTF-8字符串规范化,以确保在处理具有多个字符的字符时,字节比较是等效的编码为UTF-8。