本篇博客是为了记录自己在遇到password函数无法生效时的解决方案。通过使用AES_ENCRYPT(str,key)和AES_DECRYPT(str,key)进行加密和解密。
一、问题
自己想创建一个user表,user表中有一个password属性列,自己想对密码进行加密后再存入数据库,于是想到了之前学到的一个函数password函数,但在使用时给我报了下面这个奇怪的错误:
一开始我还觉得是不是我的插入的sql语句写的有问题,后来才知道在MySQL 8.0中,PASSWORD()
函数已被弃用。 于是又查了自己系统中的MySQL版本,发现果然是8.0以后的版本。
二、解决方案
为了实现在MySQL数据库中保存加密后的密码,自己使用了AES_ENCRYPT(str,key)函数进行加密,在存入数据库的时候,转成十六进制。str
:要加密的字符串,key
:用于加密的密钥字符串。AES_ENCRYPT()
函数返回一个二进制字符串,表示加密后的密文。如果参数为NULL
,则返回NULL
。
下面是一段实例代码:
bool insert(Json::Value &user) // 注册时新增用户
{
Json::Value val;
//用户查找函数,如果用户已经存在了就不再插入数据库
bool ret = select_by_name(user["username"].asCString(), val);
if(ret)
{
//日志打印函数
LOG(DEBUG, "user %s exists!, insert failed\n", user["username"].asCString());
return false;
}
char sql[1024] = {0};
#define INSERT_T "insert into user values(null, '%s',hex(aes_encrypt(('%s'),'mima')), 1000, 0, 0);"
sprintf(sql, INSERT_T,
user["username"].asCString(), user["pass"].asCString());
//封装的mysql执行函数
ret = mysql_util::mysql_exec(_mysql, sql);
if(!ret)
{
LOG(ERROR, "insert user failed\n");
return false;
}
return true;
}
密码就被加密后转换成十六进制存入数据库了。
解密函数 AES_DECRYPT(str,key),AES_DECRYPT和AES_ENCRYPT的key要相同,解密之前先用huhex函数转一次。然而,这里有一个问题:AES_DECRYPT
返回的是二进制数据,而你可能希望看到解密后的明文字符串。由于MySQL的字符串处理函数通常期望输入是有效的字符编码,直接显示二进制数据可能会导致乱码。为了解决这个问题,你可以将解密后的二进制数据转换为十六进制字符串进行查看(但这不是真正的解密后的明文),你看到的实际上也就是十六进制数据。
如果你只是想在MySQL中查看解密后的明文(假设明文是有效的UTF-8),你可以尝试使用CONVERT()
函数将二进制数据转换为字符类型,但这只有在解密后的数据确实是有效的字符编码时才会工作:
SELECT CONVERT(AES_DECRYPT(UNHEX(pass), '112233') USING utf8) AS deccrypted_pass_str from user where username='小彬';
using utf8部分应该与你的数据库或表的字符集设置相匹配。如果解密后的数据不是有效的UTF-8编码,这个查询可能会失败或返回乱码。