我今天遇到了一个有趣的问题。在我的用户表中,所有字段都是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',可能会让charsets混淆,但我尝试了只有md5 salt
而没有其他输入的简单测试选择,但仍然存在字符编码错误。
我认为将md5转换为latin1进行比较是一个选项,另一个可能是将密码列设置为utf8_general_ci。我的问题是:
为什么呢?为什么md5会返回看似utf8的内容,即使你提供的部分采用不同的编码?
答案 0 :(得分:3)
某些加密函数返回ASCII字符串:MD5(),OLD_PASSWORD(),PASSWORD(),SHA(),SHA1()。从MySQL 5.5.3开始,它们的返回值是一个非二进制字符串,它具有由character_set_connection和collation_connection系统变量确定的字符集和排序规则。在5.5.3之前,这些函数返回二进制字符串。对MySQL 5.5.6中的SHA2()进行了相同的更改。
除了您已经提到的内容之外,您还可以更改列定义。您真的希望根据瑞典语中使用的规则对您的密码哈希值进行排序和比较吗?也许binary
或varbinary
可能是更好的列类型。