最近看到很多人都在看Qt怎么使用QSettings记住用户名密码。
QSettings类提供了Qt对配置文件的操作,最直接的是对 ini 配置文件的操作。用它来简单的做记住用户名密码的操作是有局限性的。
因为如果是简单的最直接的操作并没有做其他操作的话,ini 配置文件是明文的,相对来说,是数据不安全的。特别是针对密码这种很敏感的信息来说。
我们用QSettings类来操作ini文件。
下面我们先定义几个宏定义函数,方便后面的操作。定义这几个函数的目的是为了偷懒,毕竟如果后续可能会有很多的相同的代码。
#define LOAD_CFG_VARIANT(x) cfg.value(x)
#define SAVE_CFG_VARIANT(x, y) cfg.setValue(x, y)
#define REMOVE_CFG_VARIANT(x) cfg.remove(x)
我们再用一个宏来定义一个固定的路径。
#define CONFIGPATH QCoreApplication::applicationDirPath() + "/config/"
我们同样提供两个函数,设置和读取配置的函数。
QVariant FileHelper::getSettings(const QString& group, const QString& key)
{
QSettings cfg(CONFIGPATH + "config.ini", QSettings::IniFormat);
cfg.beginGroup(group);
QVariant value = LOAD_CFG_VARIANT(key);
cfg.endGroup();
return value;
}
上面这个函数是读取配置的方法,返回值使用 QVariant
类型是因为,配置文件是可能保存任何类型的数据,我们也就能够通过模板的读取方式来获取相对应的值。
FileHelper::instance().getSettings("", "").value<T>();
设置配置文件的时候有也使用 QVariant
类型。
void FileHelper::setSettings(const QString& group, const QString& key, const QVariant& value)
{
QSettings cfg(CONFIGPATH + "config.ini", QSettings::IniFormat);
cfg.beginGroup(group);
SAVE_CFG_VARIANT(key, value);
cfg.endGroup();
}
如上所示是设置配置文件的方法。
有了上面的这两个方法,我们还可以拓展延伸很多的方法。比如,一次设置或者读取一个Group的所有数据。
使用QSettings
类最主要的方法,也就是读取合和设置了。有了上面这两个方法,其他多记住密码等也都只是单纯的使用这两个方法实现业务逻辑。
下面的函数在LoginDialog的构造函数中被执行,也就是在被构造的时候读取配置文件并初始化界面。
void LoginDialog::initPage()
{
QString r = FileHelper::instance().getSettings("", "").value<QString>();
ui->btnRemember->setChecked(FileHelper::instance().getSettings("Login", "remember").toBool());
ui->btnAutoLogin->setChecked(FileHelper::instance().getSettings("Login", "auto").toBool());
if(ui->btnAutoLogin->isChecked() || ui->btnRemember->isChecked())
{
ui->lnName->setText(FileHelper::instance().getSettings("Login", "user").toString());
ui->lnPasswd->setText(FileHelper::instance().getSettings("Login", "pwd").toString());
}
if(ui->btnAutoLogin->isChecked())
{
//@todo...
//ui->btnLogin->click();
}
}
而对登陆和取消的按钮操作如下:
connect(ui->btnCancel, &QPushButton::clicked, [=]{
reject();
});
LoginDialog我们使用了QDialog,选择这个类主要是因为模特框的特性。
connect(ui->btnLogin, &QPushButton::clicked, this, [this]{
QFuture<bool> func = QtConcurrent::run(this, &LoginDialog::onLogin, ui->lnName->text(), ui->lnPasswd->text());
if(func.result())
{
//successfully, @todo something...
qDebug() << "Login " << func.result();
if(ui->btnAutoLogin->isChecked() || ui->btnRemember->isChecked())
{
FileHelper::instance().setSettings("Login", "user", ui->lnName->text());
FileHelper::instance().setSettings("Login", "pwd", ui->lnPasswd->text());
FileHelper::instance().setSettings("Login", "remember", ui->btnRemember->isChecked());
FileHelper::instance().setSettings("Login", "auto", ui->btnAutoLogin->isChecked());
}
accept();
}
});
如上,我们就实现了记住密码的配置文件操作。
使用QSettings类在记住密码的这个功能上其实不是最好的选择,主要是因为数据的安全性没办法保证。
如果要考虑记住密码,建议使用加密数据库,或者对配置文件进行加密处理,以保证数据安全。
测试代码。