💂 个人主页:pp不会算法^ v ^
🤟 版权: 本文由【pp不会算法v】原创、在CSDN首发、需要转载请联系博主
💬 如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连)和订阅专栏哦
文章目录
- 简介
- 编译安装
- 使用
- 可视化工具查看
- 完结
简介
在客户端存储数据的时候很多情况都会使用sqlite,像微信这种主流软件在客户端储存数据也用到了sqlite,
但是普通的sqlite是没有加密的也就是说别人可以直接打开那个.db文件查看存储的内容,
针对数据安全,有两种方案:
一种就是将写入的数据加密,这样就算别人打开也是加密后的内容
另一种就是对数据库本身加密,sqlite官方提供也一个加密版本但是那是商业收费的
但是还是有两款开源的基于sqlite的加密数据库sqlitecipher和wxsqlite
wxsqlite3是基于sqlitecipher的,
我下面介绍的这个qt插件就是基于wxsqlite的
编译安装
github链接:https://github.com/devbean/QtCipherSqlitePlugin.git
不要用gitee上那个镜像,那个稍微有点问题(别问为什么我用过出了问题)
把代码拉取下来之后直接打开pro文件用mingw编译,编译完之后在生成目录下的
plugins/sqldrivers/这个目录下生成如下图的三个库文件
然后将下面这两个文件复制导对对应编译器的:D:\ITSoftWare\QT5.15.2\Qtbase\5.15.2\mingw81_64\plugins\sqldrivers(以我的为例我是用mingw81_64编译的,release和debug模式编译的都一样)中
然后把下面这个.a文件放到对应编译器目录的lib目录下:D:\ITSoftWare\QT5.15.2\Qtbase\5.15.2\mingw81_64\lib(以我的为例)
使用
输出QSqlDatabase::drivers()看一看时候包含了 SQLITECIPHER,如果包含了那么证明安装成功了
使用和qt的sqlite模块基本一致,
只要在初始化数据库的时候添加一下密码就行了,
db_ = QSqlDatabase::addDatabase(“SQLITECIPHER”, connectionName_);
db_.setPassword(“123698745”);
示例代码:
#include <QtSql>
#include <QCoreApplication>
#include <QTemporaryDir>
#ifndef QT_DEBUG
#error Must be built in debug mode!
#endif
#ifdef Q_OS_IOS
# include <QtPlugin>
Q_IMPORT_PLUGIN(SqliteCipherDriverPlugin)
#endif
#define CONNECTION_FAILED -1
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
Q_UNUSED(app)
qDebug() << QSqlDatabase::drivers();
Q_ASSERT(QSqlDatabase::isDriverAvailable("QSQLITE")); // from Qt
Q_ASSERT(QSqlDatabase::isDriverAvailable("SQLITECIPHER")); // from our plugin
QTemporaryDir tmp;
Q_ASSERT(tmp.isValid());
auto withDB = [&](const char *driver, auto fn) {
QString path = QDir(tmp.path()).absoluteFilePath(QString(driver) + ".db");
{
QSqlDatabase db = QSqlDatabase::addDatabase(driver, "db");
db.setDatabaseName(path);
Q_ASSERT(db.open());
fn(db);
}
QSqlDatabase::removeDatabase("db");
};
// // QSQLITE
// {
// // Create a SQLite db
// withDB("QSQLITE", [](auto db) {
// db.exec("create table foo (bar integer)");
// db.exec("insert into foo values (42)");
// });
// // Check that we can read from the SQLite db
// withDB("QSQLITE", [](auto db) {
// QSqlQuery q = db.exec("select bar from foo");
// Q_ASSERT(q.next());
// Q_ASSERT(q.value(0).toInt() == 42);
// });
// // Check that SQLite is not SQLCipher
// withDB("QSQLITE", [](auto db) {
// QSqlQuery q = db.exec("select sqlcipher_export()");
// QString errmsg = q.lastError().databaseText();
// Q_ASSERT(errmsg.startsWith("no such function"));
// });
// }
// // SQLITECIPHER
// {
// // Check that SQLiteCipher is not SQLite
// withDB("SQLITECIPHER", [](auto db) {
// QSqlQuery q = db.exec("select sqlcipher_export()");
// QString errmsg = q.lastError().databaseText();
// qDebug() << errmsg;
// Q_ASSERT(errmsg.startsWith("wrong number of arguments"));
// });
// // Create a SQLiteCipher db with a passphrase
// withDB("SQLITECIPHER", [](auto db) {
// db.exec("pragma key='foobar'");
// db.exec("create table foo (bar integer)");
// db.exec("insert into foo values (42)");
// });
// // Check that we can't read from the SQLiteCipher db without the passphrase
// withDB("SQLITECIPHER", [](auto db) {
// QSqlQuery q = db.exec("select bar from foo");
// Q_ASSERT(!q.next());
// });
// // Check that we can read from the SQLiteCipher db with the passphrase
// withDB("SQLITECIPHER", [](auto db) {
// db.exec("pragma key='foobar'");
// QSqlQuery q = db.exec("select bar from foo");
// Q_ASSERT(q.next());
// Q_ASSERT(q.value(0).toInt() == 42);
// });
// }
QString dir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
// QString DB_FILE_PATH = dir + "/test_chacha20.db";
QString DB_FILE_PATH = dir + "/local.db";
qDebug() << "DB File Path is:" << DB_FILE_PATH;
QSqlDatabase dbconn = QSqlDatabase::addDatabase("SQLITECIPHER");
dbconn.setDatabaseName(DB_FILE_PATH); //localDB.db is already existing before running the application
dbconn.setPassword("pass");
dbconn.setConnectOptions("QSQLITE_USE_CIPHER=sqlcipher; SQLCIPHER_LEGACY=1; SQLCIPHER_LEGACY_PAGE_SIZE=4096; QSQLITE_CREATE_KEY");
bool open = dbconn.open();
qDebug() << "open: " << open;
qDebug() << "isOpen(): " << dbconn.isOpen() << dbconn.isOpenError();
qDebug() << "create_key: " << dbconn.lastError();
if (!dbconn.isOpen())
{
qDebug() << "Connection failed: " << dbconn.lastError().driverText();
exit(CONNECTION_FAILED);
}
QSqlQuery query;
// query.exec("create table test (id int, name varchar)");
// query.exec("insert into test values (1, 'AAA')");
// query.exec("insert into test values (2, 'BBB')");
// query.exec("insert into test values (3, 'CCC')");
// query.exec("insert into test values (4, 'DDD')");
// query.exec("insert into test values (5, 'EEE')");
// query.exec("insert into test values (6, 'FFF')");
// query.exec("insert into test values (7, 'GGG')");
// query.exec("select * from test where name regexp '(a|A)$'");
// if (query.next()) {
// qDebug() << "Regexp result: " << query.value(0).toInt() << ": " << query.value(1).toString();
// } else {
// qDebug() << "This plugin does not support regexp.";
// }
// qDebug() << "----------" << endl;
query.exec("select id, name from test");
while (query.next()) {
qDebug() << query.value(0).toInt() << ": " << query.value(1).toString();
}
// qDebug() << "----------" << endl;
// query.exec("update mapping set name='ZZZ' where id=1");
// query.exec("select id, name from mapping");
// while (query.next()) {
// qDebug() << query.value(0).toInt() << ": " << query.value(1).toString();
// }
// qDebug() << "----------" << endl;
// query.exec("delete from mapping where id=4");
// query.exec("select id, name from mapping");
// while (query.next()) {
// qDebug() << query.value(0).toInt() << ": " << query.value(1).toString();
// }
// query.exec("drop table mapping");
dbconn.close();
return 0;
}
可视化工具查看
由于数据库被加密了使用一般的数据库可视化工具例如Navicat查看不了,这里我们可以下载sqlitestudio这款工具,也是qt写的,安装好了之打开上述示例代码创建的数据库
完结
如果你觉得对你有帮助,那麻烦三连一下吧
qt/c++技术交流q群:287590944