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

PHP:POST和GET中的不同字符集,php,string,utf-8,character-encoding,ascii,Php,String,Utf 8,Character Encoding,Ascii,在PHP中,GET和POST请求中的字符集不同,我遇到了一个问题。情况如下: 我有一根挪威弦。这个字符串中当然可以包含挪威字符(即“Ensjøsvingen”)。如果我通过GET参数传递这个字符串,获取它并让它计数,它会报告strlen为13[这是正确的]。如果我通过POST参数传递这个字符串,获取它并让它计数,它将报告strlen为17 当我使用printf将字符串转换为十六进制时,结果如下: 获取: 45 6e 73 6a c3 b8 73 76 69 6e 67 65 6e 职位: 45

在PHP中,GET和POST请求中的字符集不同,我遇到了一个问题。情况如下:

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

当我使用printf将字符串转换为十六进制时,结果如下:

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

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

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

问题是,我使用该字符串生成一个SHA1散列供以后使用(在需要避免冲突的情况下,没有什么关键的,所以SHA1是完全好的),所以我不能使用mb_*-函数来获得完全相同的散列,不管该字符串是如何传递的


如何解决这个问题?

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


当PHP接受来自浏览器的输入时,它不使用字符编码。也就是说,对于GET参数,它确实尝试为您对它们进行unurlencode。根据浏览器对UTF-8字符串的编码方式,许多字符在UTF-8中有多个编码。完整字符有一种编码,甚至有几种不同的编码,它们使用一个基本字符并结合变音符号或其他标记来呈现相同的结果。对于支持Utf-8的语言来说,这没有问题,因为一个字符的所有编码都应该被视为相等的,然而,由于PHP甚至没有尝试使用字符编码,您可能只是遇到同一字符串的两种不同的规范化

我在这方面遇到的许多问题都是通过使用解决的,因此我总是使用一种或另一种标准形式,直接字节比较(而不是UTF-8感知字符比较)将产生相同的结果。这是所有UTF-8字符串都要记住的一件重要事情;strlen()和其他不在mb_字符串扩展中的PHP字符串函数不支持多字节,除非您启用重载,因此在使用UTF-8时将提供字节计数而不是字符计数


长话短说,在使用UTF-8时使用mb_字符串函数,您应该会有更好的结果,或者研究UTF-8字符串规范化,以确保在使用UTF-8中具有多个编码的字符时,字节比较是等效的。

您是否在表单中指定了字符集?i、 是的,我做了。不幸的是,这并没有改变任何事情。这是一个需要解决的问题,但是html_entity_decode处理许多不同格式的特殊字符,将它们更改为正确的html实体。如果通过该函数发送两个字符串,会得到相同的结果吗?它应该将两者转换为使用ø@kainaw使用htmlEntity/html_entity_decode是没有选择的,因为数据已经以错误的方式出现。这个解码过程应该在发送表单之前进行,但这不是我能做的(使用JS预修改表单是没有选择的)。我将这个答案标记为正确。将html_实体_解码与UTF-8结合使用解决了这个恼人的问题。非常感谢你!非常感谢。我很高兴你解决了这个问题。我应该先解除性爱,这样我就不会在最后得到那些烦人的额外信息。