5

我今天遇到了一个有趣的问题。在我的用户表中,所有字段都是 latin1_swedish_ci。密码存储为用户特定盐及其密码的 md5 哈希。

此查询导致错误:

SELECT * FROM users 
WHERE email = '...' 
AND password = MD5('1234' + salt)

抱怨一个#1267 - Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '='

当我将最后一行更改为:

AND password = CAST(MD5('1234' + salt) AS CHAR CHARACTER SET latin1)

查询执行得很好。

首先,我怀疑我的输入(此处为“1234”)可能会混淆字符集,但我尝试了简单的测试选择,只有一个 md5salt并且没有其他输入,但字符编码错误仍然存​​在。

我想将 md5 转换为 latin1 进行比较是一种选择,另一种可能是将密码列设置为 utf8_general_ci。然而,我的问题是:

为什么?为什么即使您输入的部分采用不同的编码,md5 也会返回似乎是 utf8 的内容?

4

1 回答 1

4

根据MySQL 文档

一些加密函数返回 ASCII 字符串:MD5()、OLD_PASSWORD()、PASSWORD()、SHA()、SHA1()。从 MySQL 5.5.3 开始,它们的返回值是一个非二进制字符串,它具有由 character_set_connection 和 collat​​ion_connection 系统变量确定的字符集和排序规则。在 5.5.3 之前,这些函数返回二进制字符串。MySQL 5.5.6 中对 SHA2() 进行了相同的更改。

除了您已经提到的内容之外,您还可以更改列定义。您真的希望根据瑞典语使用的规则对您的密码哈希进行排序和比较吗?也许binary或者varbinary会是更好的列类型。

于 2012-08-21T15:09:22.083 回答