ord与md5对疑似相同@字符表现差异的技术疑问
问题原因分析与解决方案
这是个典型的不可见Unicode控制字符搞的鬼!你看到的第二个@后面其实偷偷跟着一个视觉上完全看不见的特殊字符(比如左至右嵌入符U+202A、零宽空格U+200B这类)——这类字符不会影响视觉显示,但确确实实是字符串的一部分。
为什么会出现这种矛盾?
- PHP的
ord()函数只读取字符串的第一个字符,所以它只会返回@的ASCII码64,完全不会告诉你后面还有隐藏字符; - 而
md5()是对整个字符串的所有字节计算哈希值,包含那个看不见的特殊字符,所以两个字符串的哈希结果自然不同。
验证隐藏字符的方法
你可以用strlen()查看字符串长度,或者用bin2hex()把字符串转成十六进制编码,就能直观看到隐藏字符的存在:
php > echo strlen('@'); // 输出1,只有一个字符 php > echo strlen('@'); // 输出3(因为隐藏字符是UTF-8多字节编码) php > echo bin2hex('@'); // 输出40(@的十六进制) php > echo bin2hex('@'); // 输出40e280aa(@加上U+202A的UTF-8编码)
清理这类隐藏字符的方案
如果需要去除字符串中的这类不可见控制字符,可以用正则表达式替换掉常见的特殊控制符:
// 移除零宽空格、方向控制符、字节顺序标记等不可见字符 $cleanString = preg_replace('/[\x{200B}-\x{200D}\x{FEFF}\x{202A}-\x{202E}]/u', '', $yourString);
用户原始操作记录:
php -a Interactive shell php > echo ord('@'); 64 php > echo ord('@'); 64 php > echo md5('@'); 518ed29525738cebdac49c49e60ea9d3 php > echo md5('@'); e6124653b6620abe51d7c401a7644674 php >
内容的提问来源于stack exchange,提问作者LF-DevJourney
相关产品推荐
相关产品推荐

