Qt之程序加密授权[2]

概述:

随堂笔记欢迎批评指正
1.前面文章我们分享过生成lic文件案例Qt之程序加密授权[1]并介绍了Qt自带加密算法;
2.接下来我们分享下配套的服务器实现,包括授权文件读取,授权加密字符串判断、授权时间判断、以及相关配置文件作用;
3.服务从界面上一共有两个功能:
(1).获取当前设备详细信息,并生成.txt文件;获取设备信息
(2).读取前面文章生成的.lic文件,进行逻辑处理并告诉客户端授权是否成功;生成.lic文件

示例代码:

.h:

#pragma once

#include <QObject>
#include <QtNetwork>

class APDServer : public QObject
{
	Q_OBJECT

public:
	APDServer(QObject *parent = nullptr);
	~APDServer();

	/*
	 *  @brief:关闭服务端
	 */
	void closeServer();

	/*
	 *  @brief:创建配置文件
	 */
	bool CreateConfigFile(const QStringList &licData);

private:
	/*
	 *  @brief:初始化相关操作
	 */
	void initAll();

	/*
	*  @brief:初始化网络相关
	*/
	void initSocket();

	/*
	 *  @brief:返回加密后字符串
	 */
	QString getEncryptionStr();

	/*
	 *  @brief:读取网络配置文件
	 */
	QStringList readConfigNetWork();

	void socketEroorMessage();

private slots:
	/*
	 *  @brief: 当有新链接到来触发槽函数
	 */
	void slot_AcceptConnection();
	/**
	* @brief 当有新数据到来时调用此槽函数
	*/
	void slot_SocketReadData();
	/*
	*  @brief:当有客户端连接失败或退出时触发槽函数
	*/
	void slot_TcpError(QAbstractSocket::SocketError);
public slots :
	/*
	 *  @brief:接收lic文件路径
	 */
	void slot_RecvLicFileData(const const QStringList licList);
private:
	QTcpServer *tcpServer;  //监听套接字
	QTcpSocket *tcpSocket;  //通信套接字
	QStringList mlistLic;	//加密后字符串
	bool licFlag;			//授权成功与失败标志位
};

.cpp:

#include "APDServer.h"
#include "GlobalApiClass.h"
#include <QDir>
#include <QDate>


APDServer::APDServer(QObject *parent)
	: QObject(parent)
	,tcpServer(nullptr)
	,tcpSocket(nullptr)
	,licFlag(false)
{
	initAll();
}

APDServer::~APDServer()
{
	if (tcpServer)
	{
		delete tcpServer;
		tcpServer = nullptr;
	}
	if (tcpSocket)
	{
		delete tcpSocket;
		tcpSocket = nullptr;
	}
}

void APDServer::closeServer()
{
	tcpSocket->disconnectFromHost();
	tcpSocket->close();
	tcpServer->close();
}

bool APDServer::CreateConfigFile(const QStringList &licData)
{
	//判断路径下是否已创建文件夹没有则创建
	QDir dir("C:/Desktops");
	if (!dir.exists())
	{
		dir.mkdir("C:/Desktops");
	}
	dir.setFilter(QDir::Files);

	QString path = "C:/Desktops/License.ini";

	QSettings *config = new QSettings(path, QSettings::IniFormat);
	QString date = QDate::currentDate().toString("yyyy/MM/dd");
	QString time = QTime::currentTime().toString("hh:mm:ss");
	//写入数据
	config->setValue("/License/Start", licData.at(5));
	config->setValue("/License/End", licData.at(2));
	
	//读取数据
	QString s = config->value("/License/Start").toString();		//2020/01/22-12:12:12
	QString e = config->value("/License/End").toString();		//2025/01/22-12:12:12
	QString c = config->value("/License/Current").toString();	//2021/01/22-17:27:38

	if (c.isEmpty())
	{
		config->setValue("/License/Current", date + "-" + time);
		c = config->value("/License/Current").toString();	//2021/01/22-17:27:38
	}
		
	delete config;

	//默认授权起始时间12:12:12
	//默认授权终止时间12:12:12
	//授权起始时间
	int s_y = s.split("/").at(0).toInt();//年
	int s_m = s.split("/").at(1).toInt();//月
	int s_d = s.split("/").at(2).toInt();//日
										 //授权终止时间
	int e_y = e.split("/").at(0).toInt();
	int e_m = e.split("/").at(1).toInt();
	int e_d = e.split("/").at(2).toInt();
	//用户登录当前时间
	int f_y = c.split("-").at(0).split("/").at(0).toInt();
	int f_m = c.split("-").at(0).split("/").at(1).toInt();
	int f_d = c.split("-").at(0).split("/").at(2).toInt();
	int f_hh = c.split("-").at(1).split(":").at(0).toInt();
	int f_mm = c.split("-").at(1).split(":").at(1).toInt();
	int f_ss = c.split("-").at(1).split(":").at(2).toInt();
	//当前系统时间
	int c_y = QDate::currentDate().toString("yyyy/MM/dd").split("/").at(0).toInt();
	int c_m = QDate::currentDate().toString("yyyy/MM/dd").split("/").at(1).toInt();
	int c_d = QDate::currentDate().toString("yyyy/MM/dd").split("/").at(2).toInt();
	int c_hh = QDateTime::currentDateTime().toString("hh:mm:ss").split(":").at(0).toInt();
	int c_mm = QDateTime::currentDateTime().toString("hh:mm:ss").split(":").at(1).toInt();
	int c_ss = QDateTime::currentDateTime().toString("hh:mm:ss").split(":").at(2).toInt();

	if ((c_y > s_y) && (c_y < e_y))					//当前年 > 起始年	&&	当前年 < 终止年
		{
			if (c_y > f_y)							//当前年 > 上次登录年
			{
				return true;
			}
			else if (c_y == f_y)					//当前年 == 上次登录年
			{
				if (c_m > f_m)						//当前月 > 上次登录月
				{
					return true;
				}
				else if (c_m == f_m)				//当前月 == 上次登录月
				{
					if (c_d > f_d)					//当前日 > 上次登录日
					{
						return true;
					}
					else if (c_d == f_d)			//当前日 == 上次登录日
					{
						if (c_hh > f_hh)			//当前小时 > 上次登录小时
						{
							return true;
						}
						else if (c_hh == f_hh)		//当前小时 == 上次登录小时
						{
							if (c_mm > f_mm)		//当前分钟 > 上次登录分钟
							{
								return true;
							}
							else if (c_mm == f_mm)	//当前分钟 == 上次登录分钟
							{
								if (c_ss > f_ss)	//当前秒 > 上次登录秒
								{
									return true;
								}
								else
								{
									return false;
								}
							}
						}
						else
						{
							return false;
						}
					}
					else
					{
						return false;
					}
				}
				else
				{
					return false;
				}
			}
			else
			{
				return false;
			}
		}
	else if ((c_y == e_y))						//当前年 == 终止年
		{
			if ((c_m < e_m) && (c_m > f_m))		//当前月 < 终止月 && 当前月 > 上次登录月
			{
				return true;
			}
			else if ((c_m < e_m) && (c_m == f_m))//当前月 < 终止月 && 当前月 == 上次登录月
			{
				if (c_d > f_d)					//当前日 > 上次登录日
				{
					return true;
				}
				else if (c_d == f_d)			//当前日 ==上次登录日
				{
					if (c_hh > f_hh)			//当前小时 > 上次登录小时
					{
						return true;
					}
					else if (c_hh == f_hh)		//当前小时 == 上次登录小时
					{
						if (c_mm > f_mm)		//当前分钟 > 上次登录分钟
						{
							return true;
						}
						else if (c_mm == f_mm)	//当前分钟 == 上次登录分钟
						{
							if (c_ss > f_ss)	//当前秒 > 上次登录秒
							{
								return true;
							}
							else
							{
								return false;
							}
						}
						else
						{
							return false;
						}
					}
					else
					{
						return false;
					}
				}
				else
				{
					return false;
				}
			}
			else if (c_m == e_m)
			{
				if (c_d < e_d)
				{
					return true;
				}
				else if (c_d == e_d)
				{
					if (c_hh < 12)
					{
						return true;
					}
					else
					{
						return false;
					}
				}
				else
				{
					return false;
				}
			}
			else
			{
				return false;
			}
		}
	else if ((c_y < e_y) && (c_y == s_y))		//当前时间 < 终止时间  && 当前时间 == 起始时间
		{
			if (c_m > f_m)						//当前月 > 上次登录月
			{
				return true;
			}
			else if (c_m == f_m)				//当前月 == 上次登录月
			{
				if (c_d > f_d)					//当前日 > 上次登录日
				{
					return true;
				}
				else if (c_d == f_d)			//当前日 == 上次登录日
				{
					if (c_hh > f_hh)			//当前小时 > 上次登录小时
					{
						return true;
					}
					else if (c_hh == f_hh)		//当前小时 == 上次登录小时
					{
						if (c_mm > f_mm)		//当前分钟 > 上次登录分钟
						{
							return true;
						}
						else if (c_mm == f_mm)	//当前分钟 == 上次登录分钟
						{
							if (c_ss > f_ss)	//当前秒 > 上次登录秒
							{
								return true;
							}
							else
							{
								return false;
							}
						}
					}
					else
					{
						return false;
					}
				}
			}
		}
	return false;
}

void APDServer::initAll()
{
	initSocket();
}

void APDServer::initSocket()
{
	QStringList list = readConfigNetWork();
	if (list.isEmpty() || list.size() < 3)
		return;

	tcpServer = new QTcpServer(this);

	if (list.at(0).compare("pc") == 0)//单机
	{
		if (!tcpServer->listen(QHostAddress("127.0.0.1"), list.at(2).toInt()))//监听失败
		{
			//输出到日志
			return;
		}
	}
	else if(list.at(0).compare("pcs") == 0)//局域网
	{
		QString str = GlobalApiClass::GetInstance().getAddIP();
		if (!tcpServer->listen(QHostAddress(GlobalApiClass::GetInstance().getAddIP()), list.at(2).toInt()))//监听失败
		{
			//输出到日志
			return;
		}
	}
	connect(tcpServer, &QTcpServer::newConnection, this, &APDServer::slot_AcceptConnection);
}

QString APDServer::getEncryptionStr()
{
	if (mlistLic.isEmpty())
		return "error";

	QString lic = GlobalApiClass::GetInstance().getUserName() +
		GlobalApiClass::GetInstance().getAddIP() +
		GlobalApiClass::GetInstance().getDiskdrive() +
		GlobalApiClass::GetInstance().getHostMacAddress() +
		GlobalApiClass::GetInstance().getCpuID() +
		mlistLic.at(2) + 
		mlistLic.at(4) +
		mlistLic.at(1) +
		mlistLic.at(5);
	QByteArray hashData = QCryptographicHash::hash(lic.toLocal8Bit(), QCryptographicHash::Sha3_512);
	QString hex = hashData.toHex();
	qDebug() << "Lic:" << hex;//输出到日志
	return hex;
}

QStringList APDServer::readConfigNetWork()
{
	//读取网络配置文件
	QStringList list;
	QSettings *config = new QSettings(QCoreApplication::applicationDirPath() + "/ConfigNetWork.ini", QSettings::IniFormat);
	QString pc = config->value("/Socket/config").toString();
	QString ip = config->value("/Socket/ip").toString();
	QString port = config->value("/Socket/port").toString();
	delete config;
	list << pc << ip << port;
	return list;
}

void APDServer::socketEroorMessage()
{
	int len = tcpSocket->write("Error");
	bool flag = tcpSocket->waitForBytesWritten();	//等待数据发送完毕
	if (len > 0 && flag)
	{
		//输出到日志
	}
}

void APDServer::slot_AcceptConnection()
{
	//取出套接字
	tcpSocket = tcpServer->nextPendingConnection();
	//当有客户端发送数据时,触发信号
	connect(tcpSocket, &QTcpSocket::readyRead, this, &APDServer::slot_SocketReadData);
	//错误信息
	connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slot_TcpError(QAbstractSocket::SocketError)));
	qDebug() << "New Connect Success" << "-----" << "Server IP:" << tcpSocket->peerAddress().toString() << "LoalPort:" << tcpSocket->localPort() << "Port:" << tcpSocket->peerPort() ;
}

void APDServer::slot_SocketReadData()
{
	QByteArray buf = tcpSocket->readAll();
	nNumber++;
	if(mlistLic.isEmpty())
	{
		socketEroorMessage();
		//授权标志位
		licFlag = false;
	}
	else if (nNumber <= mlistLic.at(4).toInt())
	{
		if (buf.contains("RequestForAuthorization"))				//客户端上线发来请求授权 
		{
			if (mlistLic.at(6).compare(getEncryptionStr()) == 0)	//加密字符串相同
			{
				if (CreateConfigFile(mlistLic))
				{
					int len = tcpSocket->write("Success");
					bool flag = tcpSocket->waitForBytesWritten();	//等待数据发送完毕
					if (len > 0 && flag)
					{
						qDebug() << "Server tcpSocket->write(Success)" << len << "PC number" << nNumber;
					}
					//授权标志位
					licFlag = true;
				}
				else
				{
					socketEroorMessage();
					//授权标志位
					licFlag = false;
				}
			}
			else
			{
				socketEroorMessage();
				//授权标志位
				licFlag = false;
			}
		}
		else
		{
			socketEroorMessage();
			//授权标志位
			licFlag = false;
		}
	}
	else
	{
		socketEroorMessage();
		//授权标志位
		licFlag = false;
	}
}

void APDServer::slot_TcpError(QAbstractSocket::SocketError)
{
	int error = tcpSocket->error();
	switch (error)
	{
	case QAbstractSocket::RemoteHostClosedError://客户端断开-将客户端退出时间进更新
	{
		nNumber--;
		
		if (nNumber < 0){
			nNumber = 0;
		}

		qDebug() << "Client Disconnect IP:" << tcpSocket->QAbstractSocket::peerAddress().toString() << "PC number:" << nNumber;
		
		if (licFlag)
		{
			//授权成功情况下,客户端退出更新我们配置文件的当前时间
			QString path = "C:/Desktops/License.ini";
			//读取
			QSettings *config = new QSettings(path, QSettings::IniFormat);
			QString date = QDate::currentDate().toString("yyyy/MM/dd");
			QString time = QTime::currentTime().toString("hh:mm:ss");
			config->setValue("/License/Current", date + "-" + time);
			delete config;
		}
		//授权标志位
		licFlag = false;
		break;
	}
	default:
		break;
	}

}

void APDServer::slot_RecvLicFileData(const QStringList licList)
{
	mlistLic = licList;
}


License.ini:

[License]
Start=2021/02/24				//授权开始时间
End=2021/03/24					//授权终止时间
Current=2021/03/16-11:30:18		//客户端每次退出时间

ConfigNetWork.ini:

[Socket]
config=pc
ip=127.0.0.1
port=6688
README="[ip is Reservation]   [config = pc (Single machine)] [config = pcs (LAN)]"

说明: ConfigNetWork.ini配置文件为我们自己使用,在发布给客户使用前我们进行配置,分为单机、局域网、网络版。

运行效果图:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

over:

欢迎大家关注作者在文末评论、点赞、转发以及批评指正!
如果大家有更好的方法或有问题可以在文末评论一起讨论!
共同学习!
共同进步!

文末一句话:

青年时种下什么,老年时就收获什么。

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值