Qt 封装SQLCipherr操作数据库

最近需要使用sqlite,但sqlite是明文保存数据存在风险,在网上查了很多Qt加密sqlite的方式主要是QtCipherSqlitePlugin为主,但此种方法虽然可用Qt驱动但无法从程序外解密,不便于维护查看,故选用了SQLCipher。
SQLCipher是一个开源的软件,它提供的sqlite数据库的透明加密。开源版需要自行编译,如有需要可在本文末尾资源中心下载.lib与.dll文件
本文使用了SQLCipher的C API 参考Qt的操作方式做了一个简易封装。

头文件

#pragma once
#pragma execution_character_set("utf-8")  
#define SQLITE_HAS_CODEC
#include"sqlite3.h"
#pragma comment(lib,"sqlcipher.lib")
#pragma comment(lib,"libsqlite3.lib")
class MSqlcipher :public QObject
{
	Q_OBJECT

public:
	MSqlcipher(QObject* parent = nullptr);
	MSqlcipher(QString databaseName, QByteArray key, QObject* parent = nullptr);
	~MSqlcipher();
	bool open(QString databaseName, QByteArray key);
	bool open();
	void close();
	bool isOpen();// This will be true if the database is open
	QPair<QString, QString> getLatestError();// get lates error
	QStack<QPair<QString, QString>> getError();//get all error
	bool exec(QByteArray sql);
	bool next();
	QVariant value(ushort index);
	static bool isActive();// It will be true if the database returns the result
private:
	bool openDB();
	static int dbCallBack(void* callBackArg, int columnSize, char** columnValue, char** columnName);
	void clearContainer();
private:
	QString mDbName;
	QByteArray mKey; // sqlcipher pwd; PRAGMA key = mKey
	QStack<QPair<QString, QString>> mErrors; // first:sql second:message
	static bool mState;
	bool mIsOpen; 
	sqlite3* mDb;
	int mResult;
	static QQueue<QVariantList*> mSqlValue;
	QList<QVariant>* mCurrentValueList;
};


源文件

#include "MSqlcipher.h"
bool MSqlcipher::mState = false;
QQueue<QVariantList*> MSqlcipher::mSqlValue;
MSqlcipher::MSqlcipher(QObject* parent)
	:QObject(parent), mDb(nullptr), mIsOpen(false)
	, mResult(0), mCurrentValueList(nullptr)
{
	
}
MSqlcipher::MSqlcipher(QString databaseName, QByteArray key, QObject* parent)
	: QObject(parent), mDb(nullptr), mKey(key), mDbName(databaseName)
	, mIsOpen(false), mResult(0), mCurrentValueList(nullptr)
{

}
MSqlcipher::~MSqlcipher()
{
	close();
}

bool MSqlcipher::open(QString databaseName, QByteArray key)
{
	if (mIsOpen)
	{
		QPair<QByteArray, QByteArray> infor(QByteArray(), "sql is opened");
		mErrors.push(infor);
		return false;
	}
	mDbName = databaseName;
	mKey = key;
	return  openDB();
}

bool MSqlcipher::open()
{
	if (mIsOpen)
	{
		QPair<QByteArray, QByteArray> infor(QByteArray(), "sql is opened");
		mErrors.push(infor);
		return false;
	}
	return openDB();
}

void MSqlcipher::close()
{
	if (!mResult)
		return;
	mResult = sqlite3_close(mDb);
	mErrors.clear();
	mIsOpen = false;
	clearContainer();
}

bool MSqlcipher::isOpen()
{
	return mIsOpen;
}

QPair<QString, QString> MSqlcipher::getLatestError()
{
	if (mErrors.isEmpty())
		return {};
	return mErrors.pop();
}

QStack<QPair<QString, QString>> MSqlcipher::getError()
{
	QStack<QPair<QString, QString>> result = mErrors;
	mErrors.clear();
	return result;
}

bool MSqlcipher::exec(QByteArray sql)
{
	clearContainer();
	mResult = sqlite3_exec(mDb, sql.data(), &MSqlcipher::dbCallBack, nullptr, nullptr);
	if (mResult != SQLITE_OK)
	{
		QString errorInfor = "sql exec fail" + QString(sqlite3_errmsg(mDb));
		QPair<QString, QString> infor(sql, errorInfor);
		mErrors.push(infor);
		return false;
	}
	return true;
}
void MSqlcipher::clearContainer()
{
	mState = false;
	if (mCurrentValueList != nullptr)
	{
		delete mCurrentValueList;
		mCurrentValueList = nullptr;
	}
	while (!mSqlValue.isEmpty())
		delete mSqlValue.dequeue();
}
bool MSqlcipher::next()
{
	if (mCurrentValueList != nullptr)
	{
		delete mCurrentValueList;
		mCurrentValueList = nullptr;
	}
	if (mSqlValue.isEmpty())
	{
		mState = false;
		return false;
	}
	mCurrentValueList = mSqlValue.dequeue();
	return true;
}

QVariant MSqlcipher::value(ushort index)
{
	if (mCurrentValueList == nullptr)
		return {};
	index = index >= mCurrentValueList->size() ? mCurrentValueList->size() - 1 : index;
	return mCurrentValueList->at(index);
}

bool MSqlcipher::isActive()
{
	return mState;
}

bool MSqlcipher::openDB()
{
	mResult = sqlite3_open(mDbName.toLatin1().data(), &mDb);
	if (mResult != SQLITE_OK)
	{
		QPair<QByteArray, QByteArray> infor(QByteArray(), "sql failed to open");
		mErrors.push(infor);
		return false;
	}
	mIsOpen = true;
	clearContainer();
	mResult = sqlite3_key(mDb, mKey.data(), mKey.size());
	if (mResult != SQLITE_OK)
	{
		QPair<QByteArray, QByteArray> infor(QByteArray(), "password setting failure");
		mErrors.push(infor);
		close();
		return false;
	}
	return true;
}

int MSqlcipher::dbCallBack(void* callBackArg, int columnSize, char** columnValue, char** columnName)
{
	if (!columnSize)
		return 0;
	mState = true;
	QVariantList* oneRowValue = new QVariantList;
	for (ushort i = 0; i < columnSize; i++)
		*oneRowValue << QVariant(QString(columnValue[i]));
	mSqlValue.enqueue(oneRowValue);
	return 0;
}


有好的建议请在评论区留言。
如需相关源码请转至资源中心

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Pointer=NULL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值