我有一个包含用户库的应用程序,它存储在 xml 文件中并在程序开始时加载。为此,我使用 QXmlStreamWriter/Reader。当我尝试序列化加密(散列?)形式的密码时出现问题(为此使用 QCryptographicHash 和 Sha256)。
QCryptographicHash 返回 QByteArray,可以转换为 QString(使用 QXmlStreamWriter/Reader 所必需)。相关代码如下。在序列化之前一切正常(我可以登录),但是当我从 xml 读取数据时,在找到散列密码后,该函数的行为就像它找到了 EOF,并且 QXmlStreamReader 仅将大约 2 个字符加载到 QString。
代码中请忽略保留等(这是一个电影面板),相关片段是密码,我提供完整的功能以防万一。
我希望我解释了问题所在,这里是我的代码片段(注意:在添加哈希之前一切正常)
注册函数(散列,传递的是一个QString):
QString hash = QCryptographicHash::hash(pass.toUtf8(), QCryptographicHash::Sha256);
User* user_pointer;
user_pointer = new User(name, hash, admin);
书写功能:
QFile file("users/users.xml");
if(!file.open(QIODevice::WriteOnly))
throw "Error podczas otwierania bazy użytkowników!";
QXmlStreamWriter writer (&file);
writer.setAutoFormatting(true);
writer.writeStartDocument();
writer.writeStartElement("USERS");
int list_size = userList.size();
for(int i = 0; i < list_size; i++)
{
writer.writeStartElement("USER");
writer.writeTextElement("name", userList.at(i)->name);
writer.writeTextElement("pass", userList.at(i)->password);
writer.writeTextElement("admin", QString::number(userList.at(i)->is_admin));
writer.writeStartElement("RESERVATIONS");
for(int m = 0; m < userList.at(i)->reservList.size(); m++)
{
writer.writeStartElement("reservation");
writer.writeTextElement("moviename", userList.at(i)->reservList.at(m)->movie_name);
writer.writeTextElement("date", userList.at(i)->reservList.at(m)->date.toString("dd.MM.yyyy"));
writer.writeTextElement("hour", (userList.at(i)->reservList.at(m)->hour).toString("hhmm"));
writer.writeTextElement("paid", QString::number(userList.at(i)->reservList.at(m)->paid));
for(int n = 0; n < userList.at(i)->reservList.at(m)->placeList.size(); n++)
writer.writeTextElement("place", QString::number(userList.at(i)->reservList.at(m)->placeList.at(n)));
writer.writeEndElement();
}
writer.writeEndElement();
writer.writeEndElement();
}
writer.writeEndDocument();
file.close();
}
阅读功能:
QFile file("users/users.xml");
if(!file.open(QIODevice::ReadOnly))
throw "Brak bazy danych użytkowników lub błąd jej otworzenia!";
QXmlStreamReader reader;
reader.setDevice(&file);
reader.readNext();
QString user_name;
QString user_pass;
bool admin;
QString movie_name;
QTime hour;
QDate date;
bool paid;
User* user_pointer = NULL;
int user_counter = -1;
Reservation* reserv_pointer = NULL;
int reserv_counter = -1;
while(!reader.atEnd())
{
if(reader.isStartElement())
{
if(reader.name() == "USER")
{
reserv_counter = -1;
}
if(reader.name() == "name")
user_name = reader.readElementText();
if(reader.name() == "pass")
user_pass = reader.readElementText();
if(reader.name() == "admin")
{
admin = reader.readElementText().toInt();
user_pointer = new User(user_name, user_pass, admin);
userList.append(user_pointer);
user_counter++;
}
if(reader.name() == "reservation")
{
reserv_counter++;
}
if(reader.name() == "moviename")
movie_name = reader.readElementText();
if(reader.name() == "hour")
hour = QTime::fromString(reader.readElementText(), "hhmm");
if(reader.name() == "date")
date = QDate::fromString(reader.readElementText(), "dd.MM.yyyy");
if(reader.name() == "paid")
{
paid = reader.readElementText().toInt();
reserv_pointer = new Reservation(movie_name, date, hour, paid);
userList.at(user_counter)->reservList.append(reserv_pointer);
}
if(reader.name() == "place")
{
userList.at(user_counter)->reservList.at(reserv_counter)->placeList.append(reader.readElementText().toInt());
}
reader.readNextStartElement();
}
else
reader.readNext();
}
file.close();
}
最佳答案
散列值不是字符串,它是任意字节值的序列,其中一些在将其解释为字符串时可能会出现问题。
您有一个从QByteArray
到QString
的隐式转换,文档中说:
The byte array is converted to Unicode using the fromUtf8() function. This function stops conversion at the first NUL character found, or the end of the ba byte array.
例如,您可以使用指定长度的显式转换:
QString::fromUtf8(byteArray.data(), length);
正如 Frank Osterfeld 在评论中指出的那样,使用 UTF8 不是一个好主意,我已经针对我正在从事的项目对 Latin1 进行了广泛的测试,二进制数据是相同的,但是在文本中看起来“时髦”形式,它可能不适合 XML 读写,toHex()
将通过将字符集限制为 0-F 来解决这个问题:
QByteArray b; // hash
QString ss = QString::fromLatin1(b.toHex()); // to QString
b = QByteArray::fromHex(ss.toLatin1()); // back to QByteArray
关于c++ - 将加密的密码序列化为 XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40193422/