QT实现支持加密的Sqlite数据库引擎

前端之家收集整理的这篇文章主要介绍了QT实现支持加密的Sqlite数据库引擎前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

  sqlite数据库使用很广泛,我们经常会在发布一些小型软件的时候使用它,因为它不需要安装服务器。QT默认的数据库引擎是支持sqlITE数据库的,但并不支持数据库加密,不加密的sqlite数据库任何人都可以很轻易的打开它,这让我们的数据很不安全,很容易泄露或被篡改。自己对数据库进行加密当然也可以,但是那就不是通用的了,其他人用其他数据库工具也无法打开数据库文件,要想采用通用的加密方式,我们可以在网上找到sqlite3.dll这个动态库,这个动态库能够支持sqlite数据库文件加密。所以如果你想使用加密版的sqlite,第一种方式就是直接使用sqlite3.dll里面的函数,这种方式简单,但是你就无法使用QT自带数据库引擎了,这有很多缺点,用过QsqlDatabase的人应该知道,这个类可以打开很多种数据库类型,比如MysqL,sqlserver,sqlite等,而且操作函数都是一致的,这使得我们在更换不同数据库时很方便,不需要做太大的改动,另外如果你不用QT默认的数据库引擎,那么就无法使用如QsqlQueryModel进行数据的展示了。

  那么有什么更好的方法吗?当然有,实际上QT给我们提供了一种方法,就是创建新的数据库引擎。而且要实现sqlite非常简单,几乎可以用QT自带文件做很小的修改就实现。下面我们来讲一下具体的操作。

1.创建工程

打开QtCreator,新建项目,选择Library,C++库。

分享图片

类型选择:Qt plugin,项目名称sqlITEEX

分享图片

类名:QsqliteExDriverPlugin,基类选择:QsqlDriverPlugin,然后点击下一步完成创建。

分享图片

 

2.

找到你安装QT的目录,将下面两个目录复制到工程目录下:

D:\Program\Qt\Qt5.10.0\5.10.0\mingw53_32\include\QtCore\5.10.0\QtCore

D:\Program\Qt\Qt5.10.0\5.10.0\mingw53_32\include\Qtsql\5.10.0\Qtsql

然后在sqlITEEX.pro工程文件添加

INCLUDEPATH +=$$PWD/QtCore

INCLUDEPATH +=$$PWD/Qtsql

 

3.

下载sqlite3.dll,将sqlite3.lib和sliqte3.h文件放到工程目录下。将sqlite3.h添加到工程。

然后在sqlITEEX.pro工程文件添加

LIBS += -L$$PWD -lsqlite3

 

4.

新建文件qsql_sqliteex_p.h,qsql_sqliteex.cpp。然后在QT源码下找到sqlite的实现源码,例如QT5.10在以下目录:

D:\Program\Qt\Qt5.10.0\5.10.0\Src\qtbase\src\plugins\sqldrivers\sqlite

找到qsql_sqlite_p.h文件,将#define Qsql_sqlITE_H#endif中间的内容复制到qsql_sqliteex_p.h,

找到qsql_sqlite.cpp文件,将所有内容复制到qsql_sqliteex.cpp。然后将这两个文件中的类名做下修改

QsqliteDriverPrivate修改为:QsqliteExDriverPrivate

QsqliteDriver修改QsqliteExDriver

QsqliteResultPrivate修改QsqliteExResultPrivate

QsqliteResult修改QsqliteExResult

 

5.修改QsqliteExDriver::open

找到QsqliteExDriver::open函数修改内容

bool QsqliteExDriver::open(const QString & db,const QString & user,const QString & password,const QString & host,int port,const QString & conOpts)
{
    Q_D(QsqliteExDriver);
    if (isOpen())
        close();


    int timeOut = 5000;
    bool sharedCache = false;
    bool openReadOnlyOption = false;
    bool openUriOption = false;
#ifndef QT_NO_REGULAREXPRESSION
    static const QLatin1String regexpConnectOption = QLatin1String("QsqlITE3_ENABLE_REGEXP");
    bool defineRegexp = false;
    int regexpCacheSize = 25;
#endif

    const auto opts = conOpts.splitRef(QLatin1Char(‘;‘));
    for (auto option : opts) {
        option = option.trimmed();
        if (option.startsWith(QLatin1String("QsqlITE3_BUSY_TIMEOUT"))) {
            option = option.mid(20).trimmed();
            if (option.startsWith(QLatin1Char(‘=‘))) {
                bool ok;
                const int nt = option.mid(1).trimmed().toInt(&ok);
                if (ok)
                    timeOut = nt;
            }
        } else if (option == QLatin1String("QsqlITE3_OPEN_READONLY")) {
            openReadOnlyOption = true;
        } else if (option == QLatin1String("QsqlITE3_OPEN_URI")) {
            openUriOption = true;
        } else if (option == QLatin1String("QsqlITE3_ENABLE_SHARED_CACHE")) {
            sharedCache = true;
        }
#ifndef QT_NO_REGULAREXPRESSION
        else if (option.startsWith(regexpConnectOption)) {
            option = option.mid(regexpConnectOption.size()).trimmed();
            if (option.isEmpty()) {
                defineRegexp = true;
            } else if (option.startsWith(QLatin1Char(‘=‘))) {
                bool ok = false;
                const int cacheSize = option.mid(1).trimmed().toInt(&ok);
                if (ok) {
                    defineRegexp = true;
                    if (cacheSize > 0)
                        regexpCacheSize = cacheSize;
                }
            }
        }
#endif
    }

    int openMode = (openReadOnlyOption ? sqlITE_OPEN_READONLY : (sqlITE_OPEN_READWRITE | sqlITE_OPEN_CREATE));
    openMode |= (sharedCache ? sqlITE_OPEN_SHAREDCACHE : sqlITE_OPEN_PRIVATECACHE);
    if (openUriOption)
        openMode |= sqlITE_OPEN_URI;

    openMode |= sqlITE_OPEN_NOMUTEX;

    if (sqlite3_open_v2(db.toUtf8().constData(),&d->access,openMode,NULL) == sqlITE_OK) {
        if(sqlite3_key(d->access,password.toUtf8(),password.toUtf8().length()) != sqlITE_OK)
        {
            if (d->access) {
                sqlite3_close(d->access);
                d->access = 0;
            }
            setLastError(qMakeError(d->access,tr("Error opening database by key"),QsqlError::ConnectionError));
            setOpenError(true);
            return false;
        }
        sqlite3_busy_timeout(d->access,timeOut);
        setOpen(true);
        setOpenError(false);
#ifndef QT_NO_REGULAREXPRESSION
        if (defineRegexp) {
            auto cache = new QCache<QString,QRegularExpression>(regexpCacheSize);
            sqlite3_create_function_v2(d->access,"regexp",2,sqlITE_UTF8,cache,&_q_regexp,NULL,&_q_regexp_cleanup);
        }
#endif
        return true;
    } else {
        if (d->access) {
            sqlite3_close(d->access);
            d->access = 0;
        }

        setLastError(qMakeError(d->access,tr("Error opening database"),QsqlError::ConnectionError));
        setOpenError(true);
        return false;
    }
}

 6.QsqliteExDriverPlugin添加create函数

QsqliteExDriverPlugin类头文件添加公有函数

QsqlDriver* create(const QString &) Q_DECL_OVERRIDE;

 然后实现这个函数

QsqlDriver *QsqliteExDriverPlugin::create(const QString &name)
{
    if (name == QLatin1String("QsqlITEEX")) {
        QsqliteExDriver* driver = new QsqliteExDriver();
        return driver;
    }
    return 0;
}

 

7.修改sqlITEEX.json文件

修改为:

{
    "Keys" : [ "QsqlITEEX" ]
}

 

8.修改.pro文件

Debug:TARGET = sqlITEEXD
Release:TARGET = sqlITEEX
TEMPLATE = lib
CONFIG += plugin

DESTDIR = ./plugin/sqldrivers

 

9.到此修改完成,编译工程分别生成debug版的dll和release版的dll,注意发布的时候sqlite3.dll文件要放到exe目录下。

10.创建测试工程

(1)创建一个控制台程序,

分享图片

分享图片

(2)添加代码

#include <QCoreApplication>
#include <Qtsql/Qtsql>
#include <QPluginLoader>
#include <iostream>
using namespace std;
int main(int argc,char *argv[])
{
    QCoreApplication a(argc,argv);
#ifdef QT_NO_DEBUG
  QPluginLoader driverload(qApp->applicationDirPath()+"/plugin/sqldrivers/sqlITEEX.dll");
#else
  QPluginLoader driverload(qApp->applicationDirPath()+"/plugin/sqldrivers/sqlITEEXD.dll");
#endif
    if(driverload.load())
    {
        QsqlDriverPlugin *plugin=qobject_cast<QsqlDriverPlugin*>(driverload.instance());
        if(plugin)
        {
            QsqlDriver *driver=plugin->create("QsqlITEEX");
            QsqlDatabase db;
            db=QsqlDatabase::addDatabase(driver);
            db.setDatabaseName("mydatabase.db");
            db.setPassword("123456");
            if(db.open())
            {
                QsqlQuery qry(db);
                qry.exec("create table t_trade(order_id varchar(100))");
                qry.exec("insert into t_trade(order_id) values(‘10001‘)");
                qry.exec("insert into t_trade(order_id) values(‘10002‘)");
                qry.exec("select * from t_trade");
                while(qry.next())
                {
                    cout<<qry.value(0).toString().toStdString()<<endl;
                }
            }
        }
        else
            cout<<"get plugin fail"<<endl;
    }
    else
        cout<<"driver load fail"<<endl;
    return a.exec();
}

 (3)将plugin目录放到生成的exe目录下:

分享图片

分享图片

 

(4)运行结果

分享图片

 

完整工程下载:https://download.csdn.net/download/jonahking2012/10688526

猜你在找的Sqlite相关文章