From e7077ab4b5dbb041c4fbe54a2d2d81e53d964c0a Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Sat, 8 Aug 2026 10:37:42 +0800
Subject: [PATCH 01/15] update:depend library
---
XEngine_Source/XEngine_DependLibrary | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/XEngine_Source/XEngine_DependLibrary b/XEngine_Source/XEngine_DependLibrary
index 237be58..dc73149 160000
--- a/XEngine_Source/XEngine_DependLibrary
+++ b/XEngine_Source/XEngine_DependLibrary
@@ -1 +1 @@
-Subproject commit 237be589ec33bba0bf3405c095db470c1d3766b3
+Subproject commit dc73149af8aef839085e1f7ad254aea41f0a2f86
From 63827dda13626702455fb8bb0b67f2d9321a85cd Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Sat, 8 Aug 2026 10:38:24 +0800
Subject: [PATCH 02/15] fixed:does not reply when mqtt connect failure
---
.../XEngine_AuthorizeService/Authorize_MQTTTask.cpp | 2 +-
.../XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_MQTTTask.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_MQTTTask.cpp
index 377557d..7ee445f 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_MQTTTask.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_MQTTTask.cpp
@@ -87,7 +87,7 @@ bool Authorize_MQTTTask_Handle(LPCXSTR lpszClientAddr, MQTTPROTOCOL_FIXEDHEADER*
//错误断开连接
MQTTProtocol_Packet_DisConnect(tszRVBuffer, &nRVLen);
MQTTProtocol_Packet_Header(tszSDBuffer, &nSDLen, XENGINE_RFCCOMPONENTS_MQTT_PROTOCOL_TYPE_DISCONN, tszRVBuffer, nRVLen);
- //XEngine_MQXService_Send(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_MQAPP_NETTYPE_MQTT);
+ XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_MQTT);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("MQTT客户端:%s,请求链接失败,错误码:%lX"), lpszClientAddr, MQTTProtocol_GetLastError());
return false;
}
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj
index f5d112d..48728a9 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj
@@ -154,6 +154,7 @@
stdcpp20
stdc17
/utf-8 %(AdditionalOptions)
+ MultiThreadedDLL
Console
From 3f89ddb20bfc088792035d8379b4fd21475dc092 Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Sat, 8 Aug 2026 11:37:40 +0800
Subject: [PATCH 03/15] fixed:generator order incorrect fixed:ql scan problem
---
.../DBModule_MySQL/DBModule_MySQL.cpp | 20 +++++--------------
.../Protocol_Packet/Protocol_Packet.cpp | 2 --
.../Session_Authorize/Session_Authorize.cpp | 3 ---
XEngine_Source/XEngine.sln | 3 +++
.../AuthorizeHTTP_GetTask.cpp | 11 +++++-----
.../AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp | 1 -
.../Authorize_TCPTask.cpp | 2 --
7 files changed, 13 insertions(+), 29 deletions(-)
diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp
index 27fe700..09a7288 100644
--- a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp
+++ b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp
@@ -187,7 +187,6 @@ bool CDBModule_MySQL::DBModule_MySQL_UserQuery(LPCXSTR lpszUserName, AUTHREG_USE
return false;
}
XCHAR** pptszResult = DataBase_MySQL_GetResult(xhData, xhTable);
- //XLONG* pInt_Length = DataBase_MySQL_GetLength(xhData, xhTable);
if (NULL != pSt_UserInfo)
{
@@ -547,8 +546,6 @@ bool CDBModule_MySQL::DBModule_MySQL_UserList(AUTHREG_USERTABLE*** pppSt_UserInf
for (__int64u i = 0; i < nRow; i++)
{
ppszResult = DataBase_MySQL_GetResult(xhData, xhTable);
- //XLONG* pInt_Length = DataBase_MySQL_GetLength(xhData, xhTable);
-
//ID
int nFliedValue = 0;
nFliedValue++;
@@ -821,7 +818,6 @@ bool CDBModule_MySQL::DBModule_MySQL_SerialQuery(LPCXSTR lpszSerialNumber, LPAUT
return false;
}
ppszResult = DataBase_MySQL_GetResult(xhData, xhTable);
- //XLONG* pInt_Length = DataBase_MySQL_GetLength(xhData, xhTable);
if (NULL != pSt_SerialTable)
{
@@ -921,8 +917,6 @@ bool CDBModule_MySQL::DBModule_MySQL_SerialQueryAll(AUTHREG_SERIALTABLE*** pppSt
{
// 获取数据库结果
ppszResult = DataBase_MySQL_GetResult(xhData, xhTable);
- //XLONG* pInt_Length = DataBase_MySQL_GetLength(xhData, xhTable);
-
int nFliedValue = 0;
//ID
nFliedValue++;
@@ -1051,8 +1045,6 @@ bool CDBModule_MySQL::DBModule_MySQL_TryQuery(AUTHREG_TEMPVER* pSt_AuthVer)
return false;
}
ppszResult = DataBase_MySQL_GetResult(xhData, xhTable);
- //XLONG* pInt_Length = DataBase_MySQL_GetLength(xhData, xhTable);
-
//ID
int nFliedValue = 0;
nFliedValue++;
@@ -1168,8 +1160,7 @@ bool CDBModule_MySQL::DBModule_MySQL_TryClear(int nThanValue, ENUM_VERIFICATION_
for (__int64u i = 0; i < nRow; i++)
{
ppszResult = DataBase_MySQL_GetResult(xhData, xhTable);
- //XLONG* pInt_Length = DataBase_MySQL_GetLength(xhData, xhTable);
-
+
int nFliedValue = 0;
AUTHREG_TEMPVER st_AuthVer;
memset(&st_AuthVer, '\0', sizeof(AUTHREG_TEMPVER));
@@ -1315,8 +1306,7 @@ bool CDBModule_MySQL::DBModule_MySQL_TryList(AUTHREG_TEMPVER*** pppSt_AuthVer, i
for (__int64u i = 0; i < nRow; i++)
{
ppszResult = DataBase_MySQL_GetResult(xhData, xhTable);
- //XLONG* pInt_Length = DataBase_MySQL_GetLength(xhData, xhTable);
-
+
int nFliedValue = 0;
//ID
(*pppSt_AuthVer)[i]->nID = _ttxoi(ppszResult[nFliedValue]);
@@ -1496,7 +1486,7 @@ bool CDBModule_MySQL::DBModule_MySQL_BannedList(AUTHREG_BANNED*** pppSt_BannedUs
for (__int64u i = 0; i < nRow; i++)
{
ppszResult = DataBase_MySQL_GetResult(xhData, xhTable);
- //XLONG* pInt_Length = DataBase_MySQL_GetLength(xhData, xhTable);
+
int nFliedValue = 0;
AUTHREG_BANNED st_Banned;
@@ -1543,7 +1533,7 @@ bool CDBModule_MySQL::DBModule_MySQL_BannedList(AUTHREG_BANNED*** pppSt_BannedUs
memset(&st_Banned, '\0', sizeof(AUTHREG_BANNED));
ppszResult = DataBase_MySQL_GetResult(xhData, xhTable);
- //XLONG* pInt_Length = DataBase_MySQL_GetLength(xhData, xhTable);
+
int nFliedValue = 0;
//ID
@@ -1927,7 +1917,7 @@ bool CDBModule_MySQL::DBModule_MySQL_AnnouncementList(AUTHREG_ANNOUNCEMENT*** pp
for (__int64u i = 0; i < nRow; i++)
{
ppszResult = DataBase_MySQL_GetResult(xhData, xhTable);
- //XLONG* pInt_Length = DataBase_MySQL_GetLength(xhData, xhTable);
+
int nFliedValue = 0;
(*ppppSt_Announcement)[i]->nID = _ttxoll(ppszResult[nFliedValue]);
nFliedValue++;
diff --git a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp
index b41367b..c4324af 100644
--- a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp
+++ b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp
@@ -75,9 +75,7 @@ bool CProtocol_Packet::Protocol_Packet_HDRComm(XCHAR* ptszMsgBuffer, int* pInt_M
{
if (0 == pSt_ProtocolHdr->wReserve)
{
- int nRVLen = 0;
int nListCount = 6;
- XCHAR tszRVBuffer[1024];
MQTTPROTOCOL_HDRPROPERTY** ppSt_HDRProperty;
BaseLib_Memory_Malloc((XPPPMEM)&ppSt_HDRProperty, nListCount, sizeof(MQTTPROTOCOL_HDRPROPERTY));
diff --git a/XEngine_Source/AuthorizeModule_Session/Session_Authorize/Session_Authorize.cpp b/XEngine_Source/AuthorizeModule_Session/Session_Authorize/Session_Authorize.cpp
index 9815f1b..592b9d5 100644
--- a/XEngine_Source/AuthorizeModule_Session/Session_Authorize/Session_Authorize.cpp
+++ b/XEngine_Source/AuthorizeModule_Session/Session_Authorize/Session_Authorize.cpp
@@ -477,9 +477,6 @@ XHTHREAD CSession_Authorize::Session_Authorize_ActiveThread(XPVOID lParam)
stl_ListIterator->nOnlineTime = nOnlineSpan;
_tcsxcpy(stl_ListIterator->tszLeftTime, stl_ListIterator->st_UserTable.tszLeftTime);
//计算时间是否超过!
- AUTHREG_PROTOCOL_TIME st_ProtocolTimer;
- memset(&st_ProtocolTimer, '\0', sizeof(AUTHREG_PROTOCOL_TIME));
-
st_ProtocolTimer.nTimeONLine = nOnlineSpan;
st_ProtocolTimer.nTimeLeft = nLeftTime;
st_ProtocolTimer.nNetType = stl_ListIterator->nNetType;
diff --git a/XEngine_Source/XEngine.sln b/XEngine_Source/XEngine.sln
index 396adf1..ff8a8c7 100644
--- a/XEngine_Source/XEngine.sln
+++ b/XEngine_Source/XEngine.sln
@@ -76,6 +76,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_Verification", "XEn
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_MSGNotify", "XEngine_DependLibrary\XEngine_Module\XEngine_MSGNotify\XEngine_MSGNotify.vcxproj", "{E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}"
+ ProjectSection(ProjectDependencies) = postProject
+ {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} = {F1736B3F-03A2-4FC7-B045-A12BA8D724FB}
+ EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_Token", "XEngine_DependLibrary\XEngine_Module\XEngine_Token\XEngine_Token.vcxproj", "{E17E889F-D826-413F-854E-DBA6000B4DA7}"
EndProject
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_GetTask.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_GetTask.cpp
index 1a8c843..dc8bf0d 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_GetTask.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_GetTask.cpp
@@ -8,7 +8,6 @@ bool XEngine_AuthorizeHTTP_GetTask(LPCXSTR lpszClientAddr, XCHAR** pptszList, in
XCHAR tszURLValue[128] = {};
LPCXSTR lpszAPITime = _X("time");
LPCXSTR lpszAPIDCode = _X("dcode");
- LPCXSTR lpszAPINotice = _X("notice");
memset(tszSDBuffer, '\0', sizeof(tszSDBuffer));
BaseLib_String_GetKeyValue(pptszList[0], "=", tszURLKey, tszURLValue);
@@ -27,19 +26,19 @@ bool XEngine_AuthorizeHTTP_GetTask(LPCXSTR lpszClientAddr, XCHAR** pptszList, in
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,获取时间失败,无法继续,错误:%X"), lpszClientAddr, Session_GetLastError());
return false;
}
- int nListCount = 0;
+ int nClientCount = 0;
AUTHSESSION_NETCLIENT** ppSt_ListClient;
- if (!Session_Authorize_GetClient(&ppSt_ListClient, &nListCount, st_UserInfo.tszUserName))
+ if (!Session_Authorize_GetClient(&ppSt_ListClient, &nClientCount, st_UserInfo.tszUserName))
{
Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_NOTFOUND, "user not found");
XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,用户名:%s,获取时间失败,无法继续,错误:%X"), lpszClientAddr, st_UserInfo.tszUserName, Session_GetLastError());
return false;
}
- Protocol_Packet_UserTime(tszSDBuffer, &nSDLen, &ppSt_ListClient, nListCount);
- BaseLib_Memory_Free((XPPPMEM)&ppSt_ListClient, nListCount);
+ Protocol_Packet_UserTime(tszSDBuffer, &nSDLen, &ppSt_ListClient, nClientCount);
+ BaseLib_Memory_Free((XPPPMEM)&ppSt_ListClient, nClientCount);
XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP);
- XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,用户名:%s,获取时间成功,用户同时在线数:%d"), lpszClientAddr, st_UserInfo.tszUserName, nListCount);
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,用户名:%s,获取时间成功,用户同时在线数:%d"), lpszClientAddr, st_UserInfo.tszUserName, nClientCount);
}
else if (0 == _tcsxncmp(lpszAPIDCode, tszURLValue, _tcsxlen(lpszAPIDCode)))
{
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp
index 88f20ab..4024744 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp
@@ -466,7 +466,6 @@ bool XEngine_AuthorizeHTTP_User(XNETHANDLE xhToken, LPCXSTR lpszClientAddr, LPCX
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_WARN, _X("HTTP客户端:%s,序列号:%s,临时验证插入失败,因为服务器关闭了此功能"), lpszClientAddr, st_VERTemp.tszVSerial);
return false;
}
- bool bSuccess = false;
if (0 == st_AuthConfig.st_XSql.nDBType)
{
bSuccess = DBModule_SQLite_TryInsert(&st_VERTemp);
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_TCPTask.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_TCPTask.cpp
index e6ef312..b2327b9 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_TCPTask.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_TCPTask.cpp
@@ -149,7 +149,6 @@ bool XEngine_Client_TCPTask(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int n
}
else
{
- bool bSuccess = false;
//用户密码登录还是硬件吗登录
if (_tcsxlen(st_AuthProtocol.tszUserPass) > 0)
{
@@ -335,7 +334,6 @@ bool XEngine_Client_TCPTask(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int n
}
else if (ENUM_VERIFICATION_MODULE_SERIAL_TYPE_DAY == st_UserTable.enSerialType)
{
- bool bSuccess = false;
XCHAR tszIPAddr[128] = {};
_tcsxcpy(tszIPAddr, lpszClientAddr);
From 8ec9f73041e5445b1db9ae360aea7758b32eab1c Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Wed, 12 Aug 2026 16:37:50 +0800
Subject: [PATCH 04/15] added:create client id and key support for token
---
README.en.md | 5 +-
README.md | 5 +-
.../AuthorizeModule_Database.def | 10 +-
.../DBModule_MySQL/DBModule_MySQL.cpp | 137 ++++++++++++++++++
.../DBModule_MySQL/DBModule_MySQL.h | 4 +
.../DBModule_SQLite/DBModule_SQLite.cpp | 133 +++++++++++++++++
.../DBModule_SQLite/DBModule_SQLite.h | 4 +
.../Database_Define.h | 96 +++++++++++-
.../AuthorizeModule_Database/pch.cpp | 24 +++
.../Protocol_Parse/Protocol_Parse.cpp | 35 +++++
.../Protocol_Parse/Protocol_Parse.h | 1 +
XEngine_Source/XAuth_Protocol.h | 12 +-
.../AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp | 63 +++++++-
13 files changed, 516 insertions(+), 13 deletions(-)
diff --git a/README.en.md b/README.en.md
index 2b7e94e..a7dd4ea 100644
--- a/README.en.md
+++ b/README.en.md
@@ -119,7 +119,7 @@ port :tcp port 5300,websocket port 5301,http management port 5302,Transmission v
#### app packet service
If you don't have software development capabilities, don't want to implement it yourself, or want to add authorization verification to other software, we also provide an authorization packaging service, which allows your program to directly package our verification.
Program Packaging Service is a paid service, and you can package and add verification to any program. You can integrate our verification service without requiring source code or modifying your program. After packaging is complete, when it is run next time, our verification client will run first, and then your provided program will run after verification is successful, which is very convenient to use.
-This service is paid, priced at 200 per package. It supports both x86 and x64 programs, and only requires you to provide your server address, port, and verification mode. The process is as follows:
+This service is paid, priced at $20 per package. It supports both x86 and x64 programs, and only requires you to provide your server address, port, and verification mode. The process is as follows:
Payment → Send the program to us → We package it → Verification testing → Send the packaged program to you → Completed
After packaging, when the program is launched, the following window will open first. Only after a successful login will your program start. As shown below, once launched, the main interface will be displayed. After login, the main interface will close and your program will then start.

@@ -132,9 +132,10 @@ After packaging, when the program is launched, the following window will open fi
The verification timer will automatically stop. Supported features include login, local CDKEY verification, registration, recharge, password recovery, and remaining time query.
Note: This feature is only a packaging replacement. If you require full encryption, shell protection, and higher security, you must implement it yourself through code development.
#### Packager
-We can also provide the original packager if you have more packaging needs. The packager is currently in a promotional campaign, 500 yuan.
+We can also provide the original packager if you have more packaging needs. The packager is currently in a promotional campaign, $50 .
You can choose our verification program, then select the program you want to package. Then select the configuration file, and that's it. It supports automatically updating the program icon to your software icon.
Configuration file supports configuring encryption and decryption communication and authentication mode
+The packer can provide source code. It is written in C++. Please contact us if you need it

## Participate in contribution
diff --git a/README.md b/README.md
index 3183dbc..67d5dbf 100644
--- a/README.md
+++ b/README.md
@@ -130,7 +130,7 @@ Linux or macos:直接运行即可
#### 程序打包服务
如果你没有开发软件能力或者不想自己实现或者想给其他软件添加授权验证,我们也提供了授权打包服务,这个服务可以直接让你的程序打包我们的验证.
程序打包服务是一个付费服务,你可以为任意程序打包加验证.不需要源代码不修改你的程序就可以集成我们的验证服务,当打包完成后,当下次运行,就会先运行我们的验证客户端,验证通过后再运行你提供的程序,非常方便使用.
-此服务需要付费,200元3次,不限制x86或者x64位程序,你只需要告诉我们你的服务器地址端口验证模式即可.流程如下:
+此服务需要付费,100元3次,不限制x86或者x64位程序,你只需要告诉我们你的服务器地址端口验证模式即可.流程如下:
付费->发送程序给我们->我们打包->测试验证->发送打包程序给你->完成
当打包后,运行程序会优先打开下面的窗口,登录成功后才会启动你的程序,如下图,开启后会显示主界面,登录后主界面会关闭,然后启动你的程序

@@ -143,9 +143,10 @@ Linux or macos:直接运行即可
会自动结束验证计时.支持登录,本地CDKEY验证,注册,充值,找回密码,获取剩余时间.
注意:此功能只是替代打包,如果你想要完全的加密加壳安全性高的,必须自己使用代码开发.
#### 打包器
-我们也可以提供原始打包器,如果你有更多打包需求.打包器目前优惠活动中,500元.
+我们也可以提供原始打包器,如果你有更多打包需求.打包器目前优惠活动中,200元.
可以选择我们的验证程序,然后选择你要打包的程序.在选择配置文件即可,支持自动更新程序图标为你的软件图标.
配置文件支持配置加解密通信和验证模式
+打包器可以提供源码,打包器使用C++ 编写,如果你需要可以联系我们

## 参与贡献
diff --git a/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.def b/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.def
index e6c50ca..0c63e50 100644
--- a/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.def
+++ b/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.def
@@ -39,6 +39,10 @@ EXPORTS
DBModule_SQLite_AnnouncementDelete
DBModule_SQLite_AnnouncementList
+ DBModule_SQLite_OAuthInsert
+ DBModule_SQLite_OAuthDelete
+ DBModule_SQLite_OAuthList
+
DBModule_MySQL_Init
DBModule_MySQL_Destroy
@@ -73,4 +77,8 @@ EXPORTS
DBModule_MySQL_AnnouncementInsert
DBModule_MySQL_AnnouncementDelete
- DBModule_MySQL_AnnouncementList
\ No newline at end of file
+ DBModule_MySQL_AnnouncementList
+
+ DBModule_MySQL_OAuthInsert
+ DBModule_MySQL_OAuthDelete
+ DBModule_MySQL_OAuthList
\ No newline at end of file
diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp
index 09a7288..1ddb78f 100644
--- a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp
+++ b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp
@@ -1930,6 +1930,143 @@ bool CDBModule_MySQL::DBModule_MySQL_AnnouncementList(AUTHREG_ANNOUNCEMENT*** pp
DataBase_MySQL_FreeResult(xhData, xhTable);
return true;
}
+/********************************************************************
+函数名称:DBModule_MySQL_OAuthInsert
+函数功能:OAuth插入
+ 参数.一:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:输入要插入的信息
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+bool CDBModule_MySQL::DBModule_MySQL_OAuthInsert(AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ SQLPacket_IsErrorOccur = false;
+
+ if (NULL == pSt_OAuthInfo)
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_PARAMENT;
+ return false;
+ }
+ XCHAR tszSQLStr[8192] = {};
+
+ _xstprintf(tszSQLStr, _X("INSERT INTO `Authorize_OAuth`(tszUserName,tszTokenStr,tszClientID,tszClientKey,tszCreateTime,tszExpirationTime) VALUES('%s','%s','%s','%s','%s','%s')"), pSt_OAuthInfo->tszUserName, pSt_OAuthInfo->tszTokenStr, pSt_OAuthInfo->tszClientID, pSt_OAuthInfo->tszClientKey, pSt_OAuthInfo->tszCreateTime, pSt_OAuthInfo->tszExpirationTime);
+ //插入数据库
+ if (!DataBase_MySQL_Execute(xhData, tszSQLStr))
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = DataBase_GetLastError();
+ return false;
+ }
+ return true;
+}
+/********************************************************************
+函数名称:DBModule_SQLite_OAuthDelete
+函数功能:OAuth删除
+ 参数.一:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:输入要删除的信息
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+bool CDBModule_MySQL::DBModule_MySQL_OAuthDelete(AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ SQLPacket_IsErrorOccur = false;
+
+ if (NULL == pSt_OAuthInfo)
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_PARAMENT;
+ return false;
+ }
+ XCHAR tszSQLStr[8192] = {};
+
+ if (_tcsxlen(pSt_OAuthInfo->tszTokenStr) > 0)
+ {
+ _xstprintf(tszSQLStr, _X("DELETE FROM `Authorize_OAuth` WHERE tszTokenStr = '%s'"), pSt_OAuthInfo->tszTokenStr);
+ }
+ else
+ {
+ _xstprintf(tszSQLStr, _X("DELETE FROM `Authorize_OAuth` WHERE tszClientID = '%s'"), pSt_OAuthInfo->tszClientID);
+ }
+ //插入数据库
+ if (!DataBase_MySQL_Execute(xhData, tszSQLStr))
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = DataBase_GetLastError();
+ return false;
+ }
+ return true;
+}
+/********************************************************************
+函数名称:DBModule_MySQL_OAuthList
+函数功能:OAuth列举
+ 参数.一:ppppSt_OAuthInfo
+ In/Out:Out
+ 类型:三级指针
+ 可空:N
+ 意思:输出列举数据
+ 参数.二:pInt_ListCount
+ In/Out:Out
+ 类型:整数型指针
+ 可空:N
+ 意思:导出数据个数
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+bool CDBModule_MySQL::DBModule_MySQL_OAuthList(AUTHREG_OAUTHINFO*** pppSt_OAuthInfo, int* pInt_ListCount)
+{
+ SQLPacket_IsErrorOccur = false;
+
+ __int64u nRow = 0;
+ __int64u nColumn = 0;
+ XNETHANDLE xhTable = 0;
+ XCHAR** ppszResult = NULL;
+ XCHAR tszSQLStr[1024] = {};
+ _xstprintf(tszSQLStr, _X("SELECT * FROM Authorize_OAuth"));
+
+ if (!DataBase_MySQL_ExecuteQuery(xhData, &xhTable, tszSQLStr, &nRow, &nColumn))
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = DataBase_GetLastError();
+ return false;
+ }
+ *pInt_ListCount = (int)nRow;
+ BaseLib_Memory_Malloc((XPPPMEM)pppSt_OAuthInfo, (int)nRow, sizeof(AUTHREG_OAUTHINFO));
+ //轮训所有内容
+ for (__int64u i = 0; i < nRow; i++)
+ {
+ ppszResult = DataBase_MySQL_GetResult(xhData, xhTable);
+
+ int nFliedValue = 0;
+ _tcsxcpy((*pppSt_OAuthInfo)[i]->tszUserName, ppszResult[nFliedValue]);
+ nFliedValue++;
+ _tcsxcpy((*pppSt_OAuthInfo)[i]->tszTokenStr, ppszResult[nFliedValue]);
+ nFliedValue++;
+ _tcsxcpy((*pppSt_OAuthInfo)[i]->tszClientID, ppszResult[nFliedValue]);
+ nFliedValue++;
+ _tcsxcpy((*pppSt_OAuthInfo)[i]->tszClientKey, ppszResult[nFliedValue]);
+ nFliedValue++;
+ _tcsxcpy((*pppSt_OAuthInfo)[i]->tszCreateTime, ppszResult[nFliedValue]);
+ nFliedValue++;
+ _tcsxcpy((*pppSt_OAuthInfo)[i]->tszExpirationTime, ppszResult[nFliedValue]);
+ nFliedValue++;
+
+ }
+ DataBase_MySQL_FreeResult(xhData, xhTable);
+ return true;
+}
//////////////////////////////////////////////////////////////////////////
// 保护函数
//////////////////////////////////////////////////////////////////////////
diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.h b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.h
index 9945666..afeb2b5 100644
--- a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.h
+++ b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.h
@@ -55,6 +55,10 @@ class CDBModule_MySQL
bool DBModule_MySQL_AnnouncementInsert(AUTHREG_ANNOUNCEMENT* pSt_Announcement); //公告插入
bool DBModule_MySQL_AnnouncementDelete(AUTHREG_ANNOUNCEMENT* pSt_Announcement); //公告删除
bool DBModule_MySQL_AnnouncementList(AUTHREG_ANNOUNCEMENT*** ppppSt_Announcement, int* pInt_ListCount); //列举所有公告
+public:
+ bool DBModule_MySQL_OAuthInsert(AUTHREG_OAUTHINFO* pSt_OAuthInfo); //插入授权信息
+ bool DBModule_MySQL_OAuthDelete(AUTHREG_OAUTHINFO* pSt_OAuthInfo); //删除授权信息
+ bool DBModule_MySQL_OAuthList(AUTHREG_OAUTHINFO*** pppSt_OAuthInfo, int* pInt_ListCount);
protected:
bool DBModule_MySQL_UserPayTime(LPCXSTR lpszUserName, LPCXSTR lpszUserTime, LPCXSTR lpszCardTime, ENUM_VERIFICATION_MODULE_SERIAL_TYPE en_AuthSerialType, ENUM_VERIFICATION_MODULE_SERIAL_TYPE en_AuthUserType); //日期方式充值方式
private:
diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp
index 30c43e6..de85886 100644
--- a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp
+++ b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp
@@ -1797,6 +1797,139 @@ bool CDBModule_SQLite::DBModule_SQLite_AnnouncementList(AUTHREG_ANNOUNCEMENT***
DataBase_SQLite_FreeTable(ppszResult);
return true;
}
+/********************************************************************
+函数名称:DBModule_SQLite_OAuthInsert
+函数功能:OAuth插入
+ 参数.一:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:输入要插入的信息
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+bool CDBModule_SQLite::DBModule_SQLite_OAuthInsert(AUTHREG_OAUTHINFO *pSt_OAuthInfo)
+{
+ SQLPacket_IsErrorOccur = false;
+
+ if (NULL == pSt_OAuthInfo)
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_PARAMENT;
+ return false;
+ }
+ XCHAR tszSQLStr[8192] = {};
+
+ _xstprintf(tszSQLStr, _X("INSERT INTO Authorize_OAuth(tszUserName,tszTokenStr,tszClientID,tszClientKey,tszCreateTime,tszExpirationTime) VALUES('%s','%s','%s','%s','%s','%s')"), pSt_OAuthInfo->tszUserName, pSt_OAuthInfo->tszTokenStr, pSt_OAuthInfo->tszClientID, pSt_OAuthInfo->tszClientKey, pSt_OAuthInfo->tszCreateTime, pSt_OAuthInfo->tszExpirationTime);
+ //插入数据库
+ if (!DataBase_SQLite_Exec(xhData, tszSQLStr))
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = DataBase_GetLastError();
+ return false;
+ }
+ return true;
+}
+/********************************************************************
+函数名称:DBModule_SQLite_OAuthDelete
+函数功能:OAuth删除
+ 参数.一:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:输入要删除的信息
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+bool CDBModule_SQLite::DBModule_SQLite_OAuthDelete(AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ SQLPacket_IsErrorOccur = false;
+
+ if (NULL == pSt_OAuthInfo)
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_PARAMENT;
+ return false;
+ }
+ XCHAR tszSQLStr[8192] = {};
+ if (_tcsxlen(pSt_OAuthInfo->tszTokenStr) > 0)
+ {
+ _xstprintf(tszSQLStr, _X("DELETE FROM `Authorize_OAuth` WHERE tszTokenStr = '%s'"), pSt_OAuthInfo->tszTokenStr);
+ }
+ else
+ {
+ _xstprintf(tszSQLStr, _X("DELETE FROM `Authorize_OAuth` WHERE tszClientID = '%s'"), pSt_OAuthInfo->tszClientID);
+ }
+ //插入数据库
+ if (!DataBase_SQLite_Exec(xhData, tszSQLStr))
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = DataBase_GetLastError();
+ return false;
+ }
+ return true;
+}
+/********************************************************************
+函数名称:DBModule_SQLite_OAuthList
+函数功能:OAuth列举
+ 参数.一:ppppSt_OAuthInfo
+ In/Out:Out
+ 类型:三级指针
+ 可空:N
+ 意思:输出列举数据
+ 参数.二:pInt_ListCount
+ In/Out:Out
+ 类型:整数型指针
+ 可空:N
+ 意思:导出数据个数
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+bool CDBModule_SQLite::DBModule_SQLite_OAuthList(AUTHREG_OAUTHINFO*** ppppSt_OAuthInfo, int* pInt_ListCount)
+{
+ SQLPacket_IsErrorOccur = false;
+
+ int nRow = 0;
+ int nColumn = 0;
+ XCHAR** ppszResult = NULL;
+ XCHAR tszSQLStr[1024] = {};
+
+ _xstprintf(tszSQLStr, _X("SELECT * FROM Authorize_OAuth"));
+ if (!DataBase_SQLite_GetTable(xhData, tszSQLStr, &ppszResult, &nRow, &nColumn))
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = DataBase_GetLastError();
+ return false;
+ }
+ *pInt_ListCount = nRow;
+
+ BaseLib_Memory_Malloc((XPPPMEM)ppppSt_OAuthInfo, nRow, sizeof(AUTHREG_OAUTHINFO));
+ int nFliedValue = nColumn;
+ //轮训所有内容
+ for (int i = 0; i < nRow; i++)
+ {
+ _tcsxcpy((*ppppSt_OAuthInfo)[i]->tszUserName, ppszResult[nFliedValue]);
+ nFliedValue++;
+ _tcsxcpy((*ppppSt_OAuthInfo)[i]->tszTokenStr, ppszResult[nFliedValue]);
+ nFliedValue++;
+ _tcsxcpy((*ppppSt_OAuthInfo)[i]->tszClientID, ppszResult[nFliedValue]);
+ nFliedValue++;
+ _tcsxcpy((*ppppSt_OAuthInfo)[i]->tszClientKey, ppszResult[nFliedValue]);
+ nFliedValue++;
+ _tcsxcpy((*ppppSt_OAuthInfo)[i]->tszCreateTime, ppszResult[nFliedValue]);
+ nFliedValue++;
+ _tcsxcpy((*ppppSt_OAuthInfo)[i]->tszExpirationTime, ppszResult[nFliedValue]);
+ nFliedValue++;
+ }
+ DataBase_SQLite_FreeTable(ppszResult);
+ return true;
+}
//////////////////////////////////////////////////////////////////////////
// 保护函数
//////////////////////////////////////////////////////////////////////////
diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.h b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.h
index 065d097..a003e8f 100644
--- a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.h
+++ b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.h
@@ -55,6 +55,10 @@ class CDBModule_SQLite
bool DBModule_SQLite_AnnouncementInsert(AUTHREG_ANNOUNCEMENT* pSt_Announcement);
bool DBModule_SQLite_AnnouncementDelete(AUTHREG_ANNOUNCEMENT* pSt_Announcement);
bool DBModule_SQLite_AnnouncementList(AUTHREG_ANNOUNCEMENT*** ppppSt_Announcement, int* pInt_ListCount);
+public:
+ bool DBModule_SQLite_OAuthInsert(AUTHREG_OAUTHINFO* pSt_OAuthInfo);
+ bool DBModule_SQLite_OAuthDelete(AUTHREG_OAUTHINFO* pSt_OAuthInfo);
+ bool DBModule_SQLite_OAuthList(AUTHREG_OAUTHINFO*** pppSt_OAuthInfo, int* pInt_ListCount);
protected:
bool DBModule_SQLite_UserPayTime(LPCXSTR lpszUserName, LPCXSTR lpszUserTime, LPCXSTR lpszCardTime, ENUM_VERIFICATION_MODULE_SERIAL_TYPE en_AuthSerialType, ENUM_VERIFICATION_MODULE_SERIAL_TYPE en_AuthUserType);
private:
diff --git a/XEngine_Source/AuthorizeModule_Database/Database_Define.h b/XEngine_Source/AuthorizeModule_Database/Database_Define.h
index e024ac4..0d28c75 100644
--- a/XEngine_Source/AuthorizeModule_Database/Database_Define.h
+++ b/XEngine_Source/AuthorizeModule_Database/Database_Define.h
@@ -552,6 +552,53 @@ extern "C" bool DBModule_SQLite_AnnouncementDelete(AUTHREG_ANNOUNCEMENT* pSt_Ann
备注:
*********************************************************************/
extern "C" bool DBModule_SQLite_AnnouncementList(AUTHREG_ANNOUNCEMENT*** ppppSt_Announcement, int* pInt_ListCount);
+/********************************************************************
+函数名称:DBModule_SQLite_OAuthInsert
+函数功能:OAuth插入
+ 参数.一:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:输入要插入的信息
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+extern "C" bool DBModule_SQLite_OAuthInsert(AUTHREG_OAUTHINFO* pSt_OAuthInfo);
+/********************************************************************
+函数名称:DBModule_SQLite_OAuthDelete
+函数功能:OAuth删除
+ 参数.一:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:输入要删除的信息
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+extern "C" bool DBModule_SQLite_OAuthDelete(AUTHREG_OAUTHINFO* pSt_OAuthInfo);
+/********************************************************************
+函数名称:DBModule_SQLite_OAuthList
+函数功能:OAuth列举
+ 参数.一:ppppSt_OAuthInfo
+ In/Out:Out
+ 类型:三级指针
+ 可空:N
+ 意思:输出列举数据
+ 参数.二:pInt_ListCount
+ In/Out:Out
+ 类型:整数型指针
+ 可空:N
+ 意思:导出数据个数
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+extern "C" bool DBModule_SQLite_OAuthList(AUTHREG_OAUTHINFO*** pppSt_OAuthInfo, int* pInt_ListCount);
/************************************************************************/
/* MYSQL数据库服务导出函数 */
/************************************************************************/
@@ -1087,4 +1134,51 @@ extern "C" bool DBModule_MySQL_UserTime(LPCXSTR lpszUserName, __int64x nTime);
意思:是否成功
备注:
*********************************************************************/
-extern "C" bool DBModule_MySQL_QueryLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr);
\ No newline at end of file
+extern "C" bool DBModule_MySQL_QueryLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr);
+/********************************************************************
+函数名称:DBModule_MySQL_OAuthInsert
+函数功能:OAuth插入
+ 参数.一:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:输入要插入的信息
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+extern "C" bool DBModule_MySQL_OAuthInsert(AUTHREG_OAUTHINFO* pSt_OAuthInfo);
+/********************************************************************
+函数名称:DBModule_SQLite_OAuthDelete
+函数功能:OAuth删除
+ 参数.一:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:输入要删除的信息
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+extern "C" bool DBModule_MySQL_OAuthDelete(AUTHREG_OAUTHINFO* pSt_OAuthInfo);
+/********************************************************************
+函数名称:DBModule_MySQL_OAuthList
+函数功能:OAuth列举
+ 参数.一:ppppSt_OAuthInfo
+ In/Out:Out
+ 类型:三级指针
+ 可空:N
+ 意思:输出列举数据
+ 参数.二:pInt_ListCount
+ In/Out:Out
+ 类型:整数型指针
+ 可空:N
+ 意思:导出数据个数
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+extern "C" bool DBModule_MySQL_OAuthList(AUTHREG_OAUTHINFO*** pppSt_OAuthInfo, int* pInt_ListCount);
\ No newline at end of file
diff --git a/XEngine_Source/AuthorizeModule_Database/pch.cpp b/XEngine_Source/AuthorizeModule_Database/pch.cpp
index fab208b..d3d4554 100644
--- a/XEngine_Source/AuthorizeModule_Database/pch.cpp
+++ b/XEngine_Source/AuthorizeModule_Database/pch.cpp
@@ -151,6 +151,18 @@ extern "C" bool DBModule_SQLite_AnnouncementList(AUTHREG_ANNOUNCEMENT * **ppppSt
{
return m_DBSQLite.DBModule_SQLite_AnnouncementList(ppppSt_Announcement, pInt_ListCount);
}
+extern "C" bool DBModule_SQLite_OAuthInsert(AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ return m_DBSQLite.DBModule_SQLite_OAuthInsert(pSt_OAuthInfo);
+}
+extern "C" bool DBModule_SQLite_OAuthDelete(AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ return m_DBSQLite.DBModule_SQLite_OAuthDelete(pSt_OAuthInfo);
+}
+extern "C" bool DBModule_SQLite_OAuthList(AUTHREG_OAUTHINFO*** pppSt_OAuthInfo, int* pInt_ListCount)
+{
+ return m_DBSQLite.DBModule_SQLite_OAuthList(pppSt_OAuthInfo, pInt_ListCount);
+}
/************************************************************************/
/* MYSQL数据库服务导出函数 */
/************************************************************************/
@@ -273,4 +285,16 @@ extern "C" bool DBModule_MySQL_UserTime(LPCXSTR lpszUserName, __int64x nTime)
extern "C" bool DBModule_MySQL_QueryLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr)
{
return m_DBMySQL.DBModule_MySQL_QueryLogin(lpszUserName, lpszUserAddr);
+}
+extern "C" bool DBModule_MySQL_OAuthInsert(AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ return m_DBMySQL.DBModule_MySQL_OAuthInsert(pSt_OAuthInfo);
+}
+extern "C" bool DBModule_MySQL_OAuthDelete(AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ return m_DBMySQL.DBModule_MySQL_OAuthDelete(pSt_OAuthInfo);
+}
+extern "C" bool DBModule_MySQL_OAuthList(AUTHREG_OAUTHINFO*** pppSt_OAuthInfo, int* pInt_ListCount)
+{
+ return m_DBMySQL.DBModule_MySQL_OAuthList(pppSt_OAuthInfo, pInt_ListCount);
}
\ No newline at end of file
diff --git a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.cpp b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.cpp
index 40a5ed7..ec6a236 100644
--- a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.cpp
+++ b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.cpp
@@ -1134,5 +1134,40 @@ bool CProtocol_Parse::Protocol_Parse_HttpParseAnnouncement(LPCXSTR lpszMsgBuffer
{
pSt_Announcement->nID = st_JsonObject["nID"].asInt64();
}
+ return true;
+}
+
+bool CProtocol_Parse::Protocol_Parse_HttpParseOAuth(LPCXSTR lpszMsgBuffer, int nMsgLen, AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ Protocol_IsErrorOccur = false;
+
+ if ((NULL == lpszMsgBuffer) || (NULL == pSt_OAuthInfo))
+ {
+ Protocol_IsErrorOccur = true;
+ Protocol_dwErrorCode = ERROR_AUTHORIZE_MODULE_PROTOCOL_PARAMENT;
+ return false;
+ }
+ Json::Value st_JsonRoot;
+ JSONCPP_STRING st_JsonError;
+ Json::CharReaderBuilder st_ReaderBuilder;
+ std::unique_ptr const pSt_JsonReader(st_ReaderBuilder.newCharReader());
+ if (!pSt_JsonReader->parse(lpszMsgBuffer, lpszMsgBuffer + nMsgLen, &st_JsonRoot, &st_JsonError))
+ {
+ Protocol_IsErrorOccur = true;
+ Protocol_dwErrorCode = ERROR_AUTHORIZE_MODULE_PROTOCOL_PARSE;
+ return false;
+ }
+
+ Json::Value st_JsonObject = st_JsonRoot["st_OAuth"];
+
+ if (!st_JsonObject["tszClientID"].isNull())
+ {
+ _tcsxcpy(pSt_OAuthInfo->tszClientID, st_JsonObject["tszClientID"].asCString());
+ }
+ if (!st_JsonObject["tszClientKey"].isNull())
+ {
+ _tcsxcpy(pSt_OAuthInfo->tszClientKey, st_JsonObject["tszClientKey"].asCString());
+ }
+
return true;
}
\ No newline at end of file
diff --git a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.h b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.h
index 2260153..b41941d 100644
--- a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.h
+++ b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.h
@@ -34,6 +34,7 @@ class CProtocol_Parse
bool Protocol_Parse_HttpParseBanned(LPCXSTR lpszMsgBuffer, int nMsgLen, AUTHREG_BANNED* pSt_AuthBanned);
bool Protocol_Parse_HttpParseBanned2(LPCXSTR lpszMsgBuffer, int nMsgLen, int* pInt_POSStart, int* pInt_POSEnd);
bool Protocol_Parse_HttpParseAnnouncement(LPCXSTR lpszMsgBuffer, int nMsgLen, AUTHREG_ANNOUNCEMENT* pSt_Announcement);
+ bool Protocol_Parse_HttpParseOAuth(LPCXSTR lpszMsgBuffer, int nMsgLen, AUTHREG_OAUTHINFO* pSt_UserAuth);
protected:
private:
};
\ No newline at end of file
diff --git a/XEngine_Source/XAuth_Protocol.h b/XEngine_Source/XAuth_Protocol.h
index f72e310..d0a354a 100644
--- a/XEngine_Source/XAuth_Protocol.h
+++ b/XEngine_Source/XAuth_Protocol.h
@@ -123,4 +123,14 @@ typedef struct
XCHAR tszContext[4096]; //信息
XCHAR tszCreateTime[64]; //创建时间
__int64x nID; //ID
-}AUTHREG_ANNOUNCEMENT, * LPAUTHREG_ANNOUNCEMENT;
\ No newline at end of file
+}AUTHREG_ANNOUNCEMENT, * LPAUTHREG_ANNOUNCEMENT;
+//OAuth信息
+typedef struct
+{
+ XCHAR tszUserName[128]; //用户名
+ XCHAR tszTokenStr[128]; //Token
+ XCHAR tszClientID[128]; //ID
+ XCHAR tszClientKey[128]; //秘钥
+ XCHAR tszCreateTime[64]; //创建时间
+ XCHAR tszExpirationTime[64]; //过期时间
+}AUTHREG_OAUTHINFO;
\ No newline at end of file
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp
index eb5e9de..c2bd498 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp
@@ -3,16 +3,14 @@
bool XEngine_AuthorizeHTTP_Token(LPCXSTR lpszClientAddr, XCHAR** pptszList, int nListCount)
{
int nSDLen = 4096;
- XCHAR tszSDBuffer[4096];
- XCHAR tszURLKey[128];
- XCHAR tszURLValue[128];
+ XCHAR tszSDBuffer[4096] = {};
+ XCHAR tszURLKey[128] = {};
+ XCHAR tszURLValue[128] = {};
LPCXSTR lpszAPILogin = _X("login");
LPCXSTR lpszAPIUPDate = _X("update");
LPCXSTR lpszAPIClose = _X("close");
+ LPCXSTR lpszAPICreate = _X("create");
- memset(tszSDBuffer, '\0', sizeof(tszSDBuffer));
- memset(tszURLKey, '\0', sizeof(tszURLKey));
- memset(tszURLValue, '\0', sizeof(tszURLValue));
BaseLib_String_GetKeyValue(pptszList[0], "=", tszURLKey, tszURLValue);
if (0 == _tcsxncmp(lpszAPILogin, tszURLValue, _tcsxlen(lpszAPILogin)))
@@ -143,5 +141,58 @@ bool XEngine_AuthorizeHTTP_Token(LPCXSTR lpszClientAddr, XCHAR** pptszList, int
XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,请求关闭TOKEN:%s 成功"), lpszClientAddr, tszUserToken);
}
+ else if (0 == _tcsxncmp(lpszAPICreate, tszURLValue, _tcsxlen(lpszAPICreate)))
+ {
+ //http://app.xyry.org:5302/api?function=create&token=1000112345&type=0&timeout=3600
+ XCHAR tszTokenStr[128] = {};
+ XCHAR tszTokenType[128] = {};
+ XCHAR tszTimeout[128] = {};
+
+ BaseLib_String_GetKeyValue(pptszList[1], "=", tszURLKey, tszTokenStr);
+ BaseLib_String_GetKeyValue(pptszList[2], "=", tszURLKey, tszTokenType);
+ BaseLib_String_GetKeyValue(pptszList[3], "=", tszURLKey, tszTimeout);
+
+ XENGINE_PROTOCOL_USERINFO st_UserInfo = {};
+ if (!Session_Token_GetStr(tszTokenStr, &st_UserInfo))
+ {
+ Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_NOTFOUND, "user not found");
+ XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP);
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,获取TOKEN失败,不存在的Token:%s"), lpszClientAddr, tszTokenStr);
+ return false;
+ }
+ XCHAR tszTimeStr[128] = {};
+ AUTHREG_OAUTHINFO st_OAuthInfo = {};
+ XENGINE_LIBTIME st_LibTime = {};
+ _tcsxcpy(st_OAuthInfo.tszUserName, st_UserInfo.tszUserName);
+
+ if (nListCount > 4)
+ {
+ time_t nTime = time(NULL) + _ttxoi(tszTimeout);
+ BaseLib_Time_TTimeToStuTime(nTime, &st_LibTime);
+ BaseLib_Time_TimeToStr(st_OAuthInfo.tszExpirationTime, NULL, true, &st_LibTime);
+ }
+
+ if (0 == _ttxoi(tszTokenType))
+ {
+ BaseLib_Handle_CreateStr(st_OAuthInfo.tszTokenStr);
+ }
+ else
+ {
+ BaseLib_Handle_CreateStr(st_OAuthInfo.tszClientID, 16, 1);
+ BaseLib_Handle_CreateStr(st_OAuthInfo.tszClientKey);
+ }
+
+ if (0 == st_AuthConfig.st_XSql.nDBType)
+ {
+ DBModule_SQLite_OAuthInsert(&st_OAuthInfo);
+ }
+ else
+ {
+ DBModule_MySQL_OAuthInsert(&st_OAuthInfo);
+ }
+ Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen);
+ XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP);
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,请求关闭TOKEN:%s 成功"), lpszClientAddr, tszTokenStr);
+ }
return true;
}
\ No newline at end of file
From b32f395bdc96580e5f84719e1c03f1d72dfd943f Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Fri, 14 Aug 2026 14:31:13 +0800
Subject: [PATCH 05/15] modify:does not need device type for token with http
---
.../AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp
index c2bd498..c920892 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp
@@ -15,14 +15,14 @@ bool XEngine_AuthorizeHTTP_Token(LPCXSTR lpszClientAddr, XCHAR** pptszList, int
if (0 == _tcsxncmp(lpszAPILogin, tszURLValue, _tcsxlen(lpszAPILogin)))
{
- //http://app.xyry.org:5302/api?function=login&user=123123aa&pass=123123&device=1
+ //http://app.xyry.org:5302/api?function=login&user=123123aa&pass=123123
XCHAR tszUserName[128] = {};
XCHAR tszUserPass[128] = {};
XCHAR tszDeviceType[128] = {};
XNETHANDLE xhToken = 0;
AUTHREG_USERTABLE st_UserTable = {};
- if (nListCount < 4)
+ if (nListCount < 3)
{
Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_REQUEST, "request parament is incorrent");
XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP);
@@ -31,7 +31,6 @@ bool XEngine_AuthorizeHTTP_Token(LPCXSTR lpszClientAddr, XCHAR** pptszList, int
}
BaseLib_String_GetKeyValue(pptszList[1], "=", tszURLKey, tszUserName);
BaseLib_String_GetKeyValue(pptszList[2], "=", tszURLKey, tszUserPass);
- BaseLib_String_GetKeyValue(pptszList[3], "=", tszURLKey, tszDeviceType);
//是否启用了动态码
if (st_FunSwitch.bSwitchDCode)
{
From f0af397e7893372e56954276d4f2d67f4d2fe594 Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Fri, 14 Aug 2026 17:25:27 +0800
Subject: [PATCH 06/15] modify:reply work oauth create for token
---
.../XEngine_Config/XEngine_Config.json | 2 +-
.../AuthorizeModule_Protocol.def | 1 +
.../Protocol_Define.h | 24 ++++++++
.../Protocol_Packet/Protocol_Packet.cpp | 57 +++++++++++++++++++
.../Protocol_Packet/Protocol_Packet.h | 1 +
.../AuthorizeModule_Protocol/pch.cpp | 4 ++
.../AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp | 22 +++----
7 files changed, 95 insertions(+), 16 deletions(-)
diff --git a/XEngine_Release/XEngine_Config/XEngine_Config.json b/XEngine_Release/XEngine_Config/XEngine_Config.json
index ceaff53..c7c2688 100644
--- a/XEngine_Release/XEngine_Config/XEngine_Config.json
+++ b/XEngine_Release/XEngine_Config/XEngine_Config.json
@@ -54,7 +54,7 @@
}
},
"XCrypto": {
- "bEnable": true,
+ "bEnable": false,
"nCryptionType": 1,
"tszPassKey": "123123aa"
},
diff --git a/XEngine_Source/AuthorizeModule_Protocol/AuthorizeModule_Protocol.def b/XEngine_Source/AuthorizeModule_Protocol/AuthorizeModule_Protocol.def
index 3cfecc6..7bf62bf 100644
--- a/XEngine_Source/AuthorizeModule_Protocol/AuthorizeModule_Protocol.def
+++ b/XEngine_Source/AuthorizeModule_Protocol/AuthorizeModule_Protocol.def
@@ -16,6 +16,7 @@ EXPORTS
Protocol_Packet_HttpBanned
Protocol_Packet_HttpAnnouncement
Protocol_Packet_HttpTryList
+ Protocol_Packet_HttpOAuth
Protocol_Parse_WSHdr
Protocol_Parse_HttpParseToken
diff --git a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Define.h b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Define.h
index 9120942..9ad1abc 100644
--- a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Define.h
+++ b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Define.h
@@ -399,6 +399,30 @@ extern "C" bool Protocol_Packet_HttpAnnouncement(XCHAR* ptszMsgBuffer, int* pInt
备注:
*********************************************************************/
extern "C" bool Protocol_Packet_HttpTryList(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, AUTHREG_TEMPVER*** pppSt_TryList, int nListCount);
+/********************************************************************
+函数名称:Protocol_Packet_HttpOAuth
+函数功能:打包创建的OAuth信息
+ 参数.一:ptszMsgBuffer
+ In/Out:Out
+ 类型:字符指针
+ 可空:N
+ 意思:导出包装好的缓冲区
+ 参数.二:pInt_MsgLen
+ In/Out:Out
+ 类型:整数型指针
+ 可空:N
+ 意思:输出包装大小
+ 参数.三:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:输入要打包的信息
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+extern "C" bool Protocol_Packet_HttpOAuth(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, AUTHREG_OAUTHINFO* pSt_OAuthInfo);
/************************************************************************/
/* 解析类协议 */
/************************************************************************/
diff --git a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp
index c4324af..608cb69 100644
--- a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp
+++ b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp
@@ -957,6 +957,63 @@ bool CProtocol_Packet::Protocol_Packet_HttpTryList(XCHAR* ptszMsgBuffer, int* pI
st_JsonRoot["Count"] = st_JsonArray.size();
st_JsonRoot["Array"] = st_JsonArray;
+ *pInt_MsgLen = st_JsonRoot.toStyledString().length();
+ memcpy(ptszMsgBuffer, st_JsonRoot.toStyledString().c_str(), *pInt_MsgLen);
+ return true;
+}
+/********************************************************************
+函数名称:Protocol_Packet_HttpOAuth
+函数功能:打包创建的OAuth信息
+ 参数.一:ptszMsgBuffer
+ In/Out:Out
+ 类型:字符指针
+ 可空:N
+ 意思:导出包装好的缓冲区
+ 参数.二:pInt_MsgLen
+ In/Out:Out
+ 类型:整数型指针
+ 可空:N
+ 意思:输出包装大小
+ 参数.三:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:输入要打包的信息
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+bool CProtocol_Packet::Protocol_Packet_HttpOAuth(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ Protocol_IsErrorOccur = false;
+
+ if ((NULL == ptszMsgBuffer) || (NULL == pInt_MsgLen))
+ {
+ Protocol_IsErrorOccur = true;
+ Protocol_dwErrorCode = ERROR_AUTHORIZE_MODULE_PROTOCOL_PARAMENT;
+ return false;
+ }
+ Protocol_IsErrorOccur = false;
+
+ if ((NULL == ptszMsgBuffer) || (NULL == pInt_MsgLen))
+ {
+ Protocol_IsErrorOccur = true;
+ Protocol_dwErrorCode = ERROR_AUTHORIZE_MODULE_PROTOCOL_PARAMENT;
+ return false;
+ }
+ Json::Value st_JsonRoot;
+ Json::Value st_JsonOAuth;
+
+ st_JsonOAuth["tszClientID"] = pSt_OAuthInfo->tszClientID;
+ st_JsonOAuth["tszClientKey"] = pSt_OAuthInfo->tszClientKey;
+ st_JsonOAuth["tszUserName"] = pSt_OAuthInfo->tszUserName;
+ st_JsonOAuth["tszExpirationTime"] = pSt_OAuthInfo->tszExpirationTime;
+
+ st_JsonRoot["msg"] = "success";
+ st_JsonRoot["code"] = 0;
+ st_JsonRoot["st_OAuthInfo"] = st_JsonOAuth;
+
*pInt_MsgLen = st_JsonRoot.toStyledString().length();
memcpy(ptszMsgBuffer, st_JsonRoot.toStyledString().c_str(), *pInt_MsgLen);
return true;
diff --git a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.h b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.h
index ce4e0e9..14fbfb2 100644
--- a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.h
+++ b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.h
@@ -31,6 +31,7 @@ class CProtocol_Packet
bool Protocol_Packet_HttpBanned(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, AUTHREG_BANNED*** pppSt_BannedUser, int nUserCount, AUTHREG_BANNED*** pppSt_BannedAddr, int nAddrCount);
bool Protocol_Packet_HttpAnnouncement(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, AUTHREG_ANNOUNCEMENT*** pppSt_Announcement, int nListCount);
bool Protocol_Packet_HttpTryList(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, AUTHREG_TEMPVER*** pppSt_TryList, int nListCount);
+ bool Protocol_Packet_HttpOAuth(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, AUTHREG_OAUTHINFO* pSt_OAuthInfo);
protected:
private:
};
\ No newline at end of file
diff --git a/XEngine_Source/AuthorizeModule_Protocol/pch.cpp b/XEngine_Source/AuthorizeModule_Protocol/pch.cpp
index af329aa..4598f30 100644
--- a/XEngine_Source/AuthorizeModule_Protocol/pch.cpp
+++ b/XEngine_Source/AuthorizeModule_Protocol/pch.cpp
@@ -83,6 +83,10 @@ extern "C" bool Protocol_Packet_HttpTryList(XCHAR * ptszMsgBuffer, int* pInt_Msg
{
return m_ProtocolPacket.Protocol_Packet_HttpTryList(ptszMsgBuffer, pInt_MsgLen, pppSt_TryList, nListCount);
}
+extern "C" bool Protocol_Packet_HttpOAuth(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ return m_ProtocolPacket.Protocol_Packet_HttpOAuth(ptszMsgBuffer, pInt_MsgLen, pSt_OAuthInfo);
+}
/************************************************************************/
/* 解析类协议 */
/************************************************************************/
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp
index c920892..3ca8d55 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp
@@ -142,14 +142,12 @@ bool XEngine_AuthorizeHTTP_Token(LPCXSTR lpszClientAddr, XCHAR** pptszList, int
}
else if (0 == _tcsxncmp(lpszAPICreate, tszURLValue, _tcsxlen(lpszAPICreate)))
{
- //http://app.xyry.org:5302/api?function=create&token=1000112345&type=0&timeout=3600
+ //http://127.0.0.1:5302/api?function=create&token=1000112345&timeout=3600
XCHAR tszTokenStr[128] = {};
- XCHAR tszTokenType[128] = {};
XCHAR tszTimeout[128] = {};
BaseLib_String_GetKeyValue(pptszList[1], "=", tszURLKey, tszTokenStr);
- BaseLib_String_GetKeyValue(pptszList[2], "=", tszURLKey, tszTokenType);
- BaseLib_String_GetKeyValue(pptszList[3], "=", tszURLKey, tszTimeout);
+ BaseLib_String_GetKeyValue(pptszList[2], "=", tszURLKey, tszTimeout);
XENGINE_PROTOCOL_USERINFO st_UserInfo = {};
if (!Session_Token_GetStr(tszTokenStr, &st_UserInfo))
@@ -164,22 +162,16 @@ bool XEngine_AuthorizeHTTP_Token(LPCXSTR lpszClientAddr, XCHAR** pptszList, int
XENGINE_LIBTIME st_LibTime = {};
_tcsxcpy(st_OAuthInfo.tszUserName, st_UserInfo.tszUserName);
- if (nListCount > 4)
+ if (nListCount > 2)
{
time_t nTime = time(NULL) + _ttxoi(tszTimeout);
BaseLib_Time_TTimeToStuTime(nTime, &st_LibTime);
BaseLib_Time_TimeToStr(st_OAuthInfo.tszExpirationTime, NULL, true, &st_LibTime);
}
- if (0 == _ttxoi(tszTokenType))
- {
- BaseLib_Handle_CreateStr(st_OAuthInfo.tszTokenStr);
- }
- else
- {
- BaseLib_Handle_CreateStr(st_OAuthInfo.tszClientID, 16, 1);
- BaseLib_Handle_CreateStr(st_OAuthInfo.tszClientKey);
- }
+ BaseLib_Handle_CreateStr(st_OAuthInfo.tszClientID, 16, 1);
+ BaseLib_Handle_CreateStr(st_OAuthInfo.tszClientKey);
+ BaseLib_Time_TimeToStr(st_OAuthInfo.tszCreateTime);
if (0 == st_AuthConfig.st_XSql.nDBType)
{
@@ -189,7 +181,7 @@ bool XEngine_AuthorizeHTTP_Token(LPCXSTR lpszClientAddr, XCHAR** pptszList, int
{
DBModule_MySQL_OAuthInsert(&st_OAuthInfo);
}
- Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen);
+ Protocol_Packet_HttpOAuth(tszSDBuffer, &nSDLen, &st_OAuthInfo);
XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,请求关闭TOKEN:%s 成功"), lpszClientAddr, tszTokenStr);
}
From a36c792d0f1bca25e801435fbbb48f20c0de3ed8 Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Fri, 14 Aug 2026 20:40:13 +0800
Subject: [PATCH 07/15] added:get oauth2.0 token support for http post
---
.../AuthorizeModule_Database.def | 6 +-
.../DBModule_MySQL/DBModule_MySQL.cpp | 111 +++++++++++++++++-
.../DBModule_MySQL/DBModule_MySQL.h | 2 +
.../DBModule_SQLite/DBModule_SQLite.cpp | 110 ++++++++++++++++-
.../DBModule_SQLite/DBModule_SQLite.h | 2 +
.../Database_Define.h | 58 ++++++++-
.../AuthorizeModule_Database/Database_Error.h | 3 +-
.../AuthorizeModule_Database/pch.cpp | 16 +++
.../AuthorizeModule_Protocol.def | 1 +
.../Protocol_Define.h | 24 ++++
.../Protocol_Packet/Protocol_Packet.cpp | 54 ++++++++-
.../Protocol_Packet/Protocol_Packet.h | 1 +
.../AuthorizeModule_Protocol/pch.cpp | 4 +
XEngine_Source/XAuth_Protocol.h | 3 +-
.../AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp | 8 +-
.../AuthorizeHTTP_OAuth.cpp | 62 ++++++++++
.../AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.h | 3 +
.../XEngine_AuthorizeService/Authorize_Hdr.h | 1 +
.../Authorize_HttpTask.cpp | 9 +-
.../XEngine_AuthorizeService/Makefile | 4 +-
.../XEngine_AuthorizeService.vcxproj | 2 +
.../XEngine_AuthorizeService.vcxproj.filters | 6 +
22 files changed, 469 insertions(+), 21 deletions(-)
create mode 100644 XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp
create mode 100644 XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.h
diff --git a/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.def b/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.def
index 0c63e50..df08160 100644
--- a/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.def
+++ b/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.def
@@ -42,6 +42,8 @@ EXPORTS
DBModule_SQLite_OAuthInsert
DBModule_SQLite_OAuthDelete
DBModule_SQLite_OAuthList
+ DBModule_SQLite_OAuthUPDate
+ DBModule_SQLite_OAuthQuery
DBModule_MySQL_Init
DBModule_MySQL_Destroy
@@ -81,4 +83,6 @@ EXPORTS
DBModule_MySQL_OAuthInsert
DBModule_MySQL_OAuthDelete
- DBModule_MySQL_OAuthList
\ No newline at end of file
+ DBModule_MySQL_OAuthList
+ DBModule_MySQL_OAuthUPDate
+ DBModule_MySQL_OAuthQuery
\ No newline at end of file
diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp
index 1ddb78f..c50ce0a 100644
--- a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp
+++ b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp
@@ -1955,7 +1955,7 @@ bool CDBModule_MySQL::DBModule_MySQL_OAuthInsert(AUTHREG_OAUTHINFO* pSt_OAuthInf
}
XCHAR tszSQLStr[8192] = {};
- _xstprintf(tszSQLStr, _X("INSERT INTO `Authorize_OAuth`(tszUserName,tszTokenStr,tszClientID,tszClientKey,tszCreateTime,tszExpirationTime) VALUES('%s','%s','%s','%s','%s','%s')"), pSt_OAuthInfo->tszUserName, pSt_OAuthInfo->tszTokenStr, pSt_OAuthInfo->tszClientID, pSt_OAuthInfo->tszClientKey, pSt_OAuthInfo->tszCreateTime, pSt_OAuthInfo->tszExpirationTime);
+ _xstprintf(tszSQLStr, _X("INSERT INTO `Authorize_OAuth`(tszUserName,tszTokenStr,tszUPToken,tszClientID,tszClientKey,nExpirationTime,tszCreateTime) VALUES('%s','%s','%s','%s','%s','%d','%s')"), pSt_OAuthInfo->tszUserName, pSt_OAuthInfo->tszTokenStr, pSt_OAuthInfo->tszUPToken, pSt_OAuthInfo->tszClientID, pSt_OAuthInfo->tszClientKey, pSt_OAuthInfo->nExpirationTime, pSt_OAuthInfo->tszCreateTime);
//插入数据库
if (!DataBase_MySQL_Execute(xhData, tszSQLStr))
{
@@ -2054,16 +2054,121 @@ bool CDBModule_MySQL::DBModule_MySQL_OAuthList(AUTHREG_OAUTHINFO*** pppSt_OAuthI
nFliedValue++;
_tcsxcpy((*pppSt_OAuthInfo)[i]->tszTokenStr, ppszResult[nFliedValue]);
nFliedValue++;
+ _tcsxcpy((*pppSt_OAuthInfo)[i]->tszUPToken, ppszResult[nFliedValue]);
+ nFliedValue++;
_tcsxcpy((*pppSt_OAuthInfo)[i]->tszClientID, ppszResult[nFliedValue]);
nFliedValue++;
_tcsxcpy((*pppSt_OAuthInfo)[i]->tszClientKey, ppszResult[nFliedValue]);
nFliedValue++;
- _tcsxcpy((*pppSt_OAuthInfo)[i]->tszCreateTime, ppszResult[nFliedValue]);
+ (*pppSt_OAuthInfo)[i]->nExpirationTime = _ttxoi(ppszResult[nFliedValue]);
nFliedValue++;
- _tcsxcpy((*pppSt_OAuthInfo)[i]->tszExpirationTime, ppszResult[nFliedValue]);
+ _tcsxcpy((*pppSt_OAuthInfo)[i]->tszCreateTime, ppszResult[nFliedValue]);
nFliedValue++;
+ }
+ DataBase_MySQL_FreeResult(xhData, xhTable);
+ return true;
+}
+/********************************************************************
+函数名称:DBModule_MySQL_OAuthUPDate
+函数功能:更新OAuth信息
+ 参数.一:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:要操作的数据
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+bool CDBModule_MySQL::DBModule_MySQL_OAuthUPDate(AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ SQLPacket_IsErrorOccur = false;
+
+ if (NULL == pSt_OAuthInfo)
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_PARAMENT;
+ return false;
+ }
+ XCHAR tszSQLStatement[1024] = {};
+ //处理的类型
+ _xstprintf(tszSQLStatement, _X("UPDATE Authorize_OAuth SET tszTokenStr = '%s',tszUPToken = '%s' WHERE tszClientID = '%s' AND tszClientKey = '%s'"), pSt_OAuthInfo->tszTokenStr, pSt_OAuthInfo->tszUPToken, pSt_OAuthInfo->tszClientID, pSt_OAuthInfo->tszClientKey);
+ //插入数据库
+ if (!DataBase_SQLite_Exec(xhData, tszSQLStatement))
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = DataBase_GetLastError();
+ return false;
+ }
+ return true;
+}
+/********************************************************************
+函数名称:DBModule_MySQL_OAuthQuery
+函数功能:查询OAuth信息
+ 参数.一:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:要操作的数据
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+bool CDBModule_MySQL::DBModule_MySQL_OAuthQuery(AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ SQLPacket_IsErrorOccur = false;
+ if (NULL == pSt_OAuthInfo)
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_PARAMENT;
+ return false;
+ }
+ XCHAR tszSQLStatement[1024] = {};
+ XNETHANDLE xhTable = 0;
+ __int64u nColumn = 0;
+ __int64u nRow = 0;
+ XCHAR** ppszResult = NULL;
+
+ _xstprintf(tszSQLStatement, _X("SELECT * FROM Authorize_OAuth WHERE tszClientID = '%s' AND tszClientKey = '%s'"), pSt_OAuthInfo->tszClientID, pSt_OAuthInfo->tszClientKey);
+
+ if (!DataBase_MySQL_ExecuteQuery(xhData, &xhTable, tszSQLStatement, &nRow, &nColumn))
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = DataBase_GetLastError();
+ return false;
+ }
+ if (nRow <= 0)
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_NONE;
+ return false;
+ }
+ ppszResult = DataBase_MySQL_GetResult(xhData, xhTable);
+ int nFliedValue = 0;
+ _tcsxcpy(pSt_OAuthInfo->tszUserName, ppszResult[nFliedValue]);
+ nFliedValue++;
+ if (NULL != ppszResult[nFliedValue])
+ {
+ _tcsxcpy(pSt_OAuthInfo->tszTokenStr, ppszResult[nFliedValue]);
+ }
+ nFliedValue++;
+ if (NULL != ppszResult[nFliedValue])
+ {
+ _tcsxcpy(pSt_OAuthInfo->tszUPToken, ppszResult[nFliedValue]);
}
+ nFliedValue++;
+ _tcsxcpy(pSt_OAuthInfo->tszClientID, ppszResult[nFliedValue]);
+ nFliedValue++;
+ _tcsxcpy(pSt_OAuthInfo->tszClientKey, ppszResult[nFliedValue]);
+ nFliedValue++;
+ pSt_OAuthInfo->nExpirationTime = _ttxoi(ppszResult[nFliedValue]);
+ nFliedValue++;
+ _tcsxcpy(pSt_OAuthInfo->tszCreateTime, ppszResult[nFliedValue]);
+ nFliedValue++;
+
DataBase_MySQL_FreeResult(xhData, xhTable);
return true;
}
diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.h b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.h
index afeb2b5..0f2319d 100644
--- a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.h
+++ b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.h
@@ -59,6 +59,8 @@ class CDBModule_MySQL
bool DBModule_MySQL_OAuthInsert(AUTHREG_OAUTHINFO* pSt_OAuthInfo); //插入授权信息
bool DBModule_MySQL_OAuthDelete(AUTHREG_OAUTHINFO* pSt_OAuthInfo); //删除授权信息
bool DBModule_MySQL_OAuthList(AUTHREG_OAUTHINFO*** pppSt_OAuthInfo, int* pInt_ListCount);
+ bool DBModule_MySQL_OAuthUPDate(AUTHREG_OAUTHINFO* pSt_OAuthInfo);
+ bool DBModule_MySQL_OAuthQuery(AUTHREG_OAUTHINFO* pSt_OAuthInfo);
protected:
bool DBModule_MySQL_UserPayTime(LPCXSTR lpszUserName, LPCXSTR lpszUserTime, LPCXSTR lpszCardTime, ENUM_VERIFICATION_MODULE_SERIAL_TYPE en_AuthSerialType, ENUM_VERIFICATION_MODULE_SERIAL_TYPE en_AuthUserType); //日期方式充值方式
private:
diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp
index de85886..a4105ed 100644
--- a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp
+++ b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp
@@ -580,6 +580,7 @@ bool CDBModule_SQLite::DBModule_SQLite_UserLogin(LPCXSTR lpszUserName, LPCXSTR l
SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_INSERT;
return false;
}
+
return true;
}
/********************************************************************
@@ -1822,7 +1823,7 @@ bool CDBModule_SQLite::DBModule_SQLite_OAuthInsert(AUTHREG_OAUTHINFO *pSt_OAuthI
}
XCHAR tszSQLStr[8192] = {};
- _xstprintf(tszSQLStr, _X("INSERT INTO Authorize_OAuth(tszUserName,tszTokenStr,tszClientID,tszClientKey,tszCreateTime,tszExpirationTime) VALUES('%s','%s','%s','%s','%s','%s')"), pSt_OAuthInfo->tszUserName, pSt_OAuthInfo->tszTokenStr, pSt_OAuthInfo->tszClientID, pSt_OAuthInfo->tszClientKey, pSt_OAuthInfo->tszCreateTime, pSt_OAuthInfo->tszExpirationTime);
+ _xstprintf(tszSQLStr, _X("INSERT INTO Authorize_OAuth(tszUserName,tszTokenStr,tszUPToken,tszClientID,tszClientKey,nExpirationTime,tszCreateTime) VALUES('%s','%s','%s','%s','%s','%d','%s')"), pSt_OAuthInfo->tszUserName, pSt_OAuthInfo->tszTokenStr, pSt_OAuthInfo->tszUPToken, pSt_OAuthInfo->tszClientID, pSt_OAuthInfo->tszClientKey, pSt_OAuthInfo->nExpirationTime, pSt_OAuthInfo->tszCreateTime);
//插入数据库
if (!DataBase_SQLite_Exec(xhData, tszSQLStr))
{
@@ -1918,18 +1919,121 @@ bool CDBModule_SQLite::DBModule_SQLite_OAuthList(AUTHREG_OAUTHINFO*** ppppSt_OAu
nFliedValue++;
_tcsxcpy((*ppppSt_OAuthInfo)[i]->tszTokenStr, ppszResult[nFliedValue]);
nFliedValue++;
+ _tcsxcpy((*ppppSt_OAuthInfo)[i]->tszUPToken, ppszResult[nFliedValue]);
+ nFliedValue++;
_tcsxcpy((*ppppSt_OAuthInfo)[i]->tszClientID, ppszResult[nFliedValue]);
nFliedValue++;
_tcsxcpy((*ppppSt_OAuthInfo)[i]->tszClientKey, ppszResult[nFliedValue]);
nFliedValue++;
+ (*ppppSt_OAuthInfo)[i]->nExpirationTime = _ttxoi(ppszResult[nFliedValue]);
+ nFliedValue++;
_tcsxcpy((*ppppSt_OAuthInfo)[i]->tszCreateTime, ppszResult[nFliedValue]);
nFliedValue++;
- _tcsxcpy((*ppppSt_OAuthInfo)[i]->tszExpirationTime, ppszResult[nFliedValue]);
- nFliedValue++;
}
DataBase_SQLite_FreeTable(ppszResult);
return true;
}
+/********************************************************************
+函数名称:DBModule_SQLite_OAuthUPDate
+函数功能:更新OAuth信息
+ 参数.一:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:要操作的数据
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+bool CDBModule_SQLite::DBModule_SQLite_OAuthUPDate(AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ SQLPacket_IsErrorOccur = false;
+
+ if (NULL == pSt_OAuthInfo)
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_PARAMENT;
+ return false;
+ }
+ XCHAR tszSQLStatement[1024] = {};
+ //处理的类型
+ _xstprintf(tszSQLStatement, _X("UPDATE Authorize_OAuth SET tszTokenStr = '%s',tszUPToken = '%s' WHERE tszClientID = '%s' AND tszClientKey = '%s'"), pSt_OAuthInfo->tszTokenStr, pSt_OAuthInfo->tszUPToken, pSt_OAuthInfo->tszClientID, pSt_OAuthInfo->tszClientKey);
+ //插入数据库
+ if (!DataBase_SQLite_Exec(xhData, tszSQLStatement))
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = DataBase_GetLastError();
+ return false;
+ }
+ return true;
+}
+/********************************************************************
+函数名称:DBModule_SQLite_OAuthQuery
+函数功能:查询OAuth信息
+ 参数.一:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:要操作的数据
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+bool CDBModule_SQLite::DBModule_SQLite_OAuthQuery(AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ SQLPacket_IsErrorOccur = false;
+
+ if (NULL == pSt_OAuthInfo)
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_PARAMENT;
+ return false;
+ }
+ XCHAR tszSQLStatement[1024] = {};
+ _xstprintf(tszSQLStatement, _X("SELECT * FROM Authorize_OAuth WHERE tszClientID = '%s' AND tszClientKey = '%s'"), pSt_OAuthInfo->tszClientID, pSt_OAuthInfo->tszClientKey);
+ int nRow = 0;
+ int nColumn = 0;
+ XCHAR** ppszResult = NULL;
+ if (!DataBase_SQLite_GetTable(xhData, tszSQLStatement, &ppszResult, &nRow, &nColumn))
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = DataBase_GetLastError();
+ return false;
+ }
+
+ if (nRow <= 0)
+ {
+ SQLPacket_IsErrorOccur = true;
+ SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_NOTFOUND;
+ return false;
+ }
+ int nFliedValue = nColumn;
+ _tcsxcpy(pSt_OAuthInfo->tszUserName, ppszResult[nFliedValue]);
+ nFliedValue++;
+ if (NULL != ppszResult[nFliedValue])
+ {
+ _tcsxcpy(pSt_OAuthInfo->tszTokenStr, ppszResult[nFliedValue]);
+ }
+ nFliedValue++;
+ if (NULL != ppszResult[nFliedValue])
+ {
+ _tcsxcpy(pSt_OAuthInfo->tszUPToken, ppszResult[nFliedValue]);
+ }
+ nFliedValue++;
+ _tcsxcpy(pSt_OAuthInfo->tszClientID, ppszResult[nFliedValue]);
+ nFliedValue++;
+ _tcsxcpy(pSt_OAuthInfo->tszClientKey, ppszResult[nFliedValue]);
+ nFliedValue++;
+ pSt_OAuthInfo->nExpirationTime = _ttxoi(ppszResult[nFliedValue]);
+ nFliedValue++;
+ _tcsxcpy(pSt_OAuthInfo->tszCreateTime, ppszResult[nFliedValue]);
+ nFliedValue++;
+
+ DataBase_SQLite_FreeTable(ppszResult);
+ return true;
+}
//////////////////////////////////////////////////////////////////////////
// 保护函数
//////////////////////////////////////////////////////////////////////////
diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.h b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.h
index a003e8f..6887a1c 100644
--- a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.h
+++ b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.h
@@ -59,6 +59,8 @@ class CDBModule_SQLite
bool DBModule_SQLite_OAuthInsert(AUTHREG_OAUTHINFO* pSt_OAuthInfo);
bool DBModule_SQLite_OAuthDelete(AUTHREG_OAUTHINFO* pSt_OAuthInfo);
bool DBModule_SQLite_OAuthList(AUTHREG_OAUTHINFO*** pppSt_OAuthInfo, int* pInt_ListCount);
+ bool DBModule_SQLite_OAuthUPDate(AUTHREG_OAUTHINFO* pSt_OAuthInfo);
+ bool DBModule_SQLite_OAuthQuery(AUTHREG_OAUTHINFO* pSt_OAuthInfo);
protected:
bool DBModule_SQLite_UserPayTime(LPCXSTR lpszUserName, LPCXSTR lpszUserTime, LPCXSTR lpszCardTime, ENUM_VERIFICATION_MODULE_SERIAL_TYPE en_AuthSerialType, ENUM_VERIFICATION_MODULE_SERIAL_TYPE en_AuthUserType);
private:
diff --git a/XEngine_Source/AuthorizeModule_Database/Database_Define.h b/XEngine_Source/AuthorizeModule_Database/Database_Define.h
index 0d28c75..dbf5247 100644
--- a/XEngine_Source/AuthorizeModule_Database/Database_Define.h
+++ b/XEngine_Source/AuthorizeModule_Database/Database_Define.h
@@ -599,6 +599,34 @@ extern "C" bool DBModule_SQLite_OAuthDelete(AUTHREG_OAUTHINFO* pSt_OAuthInfo);
备注:
*********************************************************************/
extern "C" bool DBModule_SQLite_OAuthList(AUTHREG_OAUTHINFO*** pppSt_OAuthInfo, int* pInt_ListCount);
+/********************************************************************
+函数名称:DBModule_SQLite_OAuthUPDate
+函数功能:更新OAuth信息
+ 参数.一:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:要操作的数据
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+extern "C" bool DBModule_SQLite_OAuthUPDate(AUTHREG_OAUTHINFO* pSt_OAuthInfo);
+/********************************************************************
+函数名称:DBModule_SQLite_OAuthQuery
+函数功能:查询OAuth信息
+ 参数.一:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:要操作的数据
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+extern "C" bool DBModule_SQLite_OAuthQuery(AUTHREG_OAUTHINFO* pSt_OAuthInfo);
/************************************************************************/
/* MYSQL数据库服务导出函数 */
/************************************************************************/
@@ -1181,4 +1209,32 @@ extern "C" bool DBModule_MySQL_OAuthDelete(AUTHREG_OAUTHINFO* pSt_OAuthInfo);
意思:是否成功
备注:
*********************************************************************/
-extern "C" bool DBModule_MySQL_OAuthList(AUTHREG_OAUTHINFO*** pppSt_OAuthInfo, int* pInt_ListCount);
\ No newline at end of file
+extern "C" bool DBModule_MySQL_OAuthList(AUTHREG_OAUTHINFO*** pppSt_OAuthInfo, int* pInt_ListCount);
+/********************************************************************
+函数名称:DBModule_MySQL_OAuthUPDate
+函数功能:更新OAuth信息
+ 参数.一:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:要操作的数据
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+extern "C" bool DBModule_MySQL_OAuthUPDate(AUTHREG_OAUTHINFO* pSt_OAuthInfo);
+/********************************************************************
+函数名称:DBModule_MySQL_OAuthQuery
+函数功能:查询OAuth信息
+ 参数.一:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:要操作的数据
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+extern "C" bool DBModule_MySQL_OAuthQuery(AUTHREG_OAUTHINFO* pSt_OAuthInfo);
\ No newline at end of file
diff --git a/XEngine_Source/AuthorizeModule_Database/Database_Error.h b/XEngine_Source/AuthorizeModule_Database/Database_Error.h
index aa6e198..893a833 100644
--- a/XEngine_Source/AuthorizeModule_Database/Database_Error.h
+++ b/XEngine_Source/AuthorizeModule_Database/Database_Error.h
@@ -36,4 +36,5 @@
#define ERROR_AUTHORIZE_MODULE_DATABASE_NONE 0x0030018 //获取失败,没有任何记录
#define ERROR_AUTHORIZE_MODULE_DATABASE_NOTENABLE 0x0030019 //没有启用.不禁用
#define ERROR_AUTHORIZE_MODULE_DATABASE_TIMELEFT 0x0030020 //超过禁用时间
-#define ERROR_AUTHORIZE_MODULE_DATABASE_BANNED 0x0030021 //被禁用
\ No newline at end of file
+#define ERROR_AUTHORIZE_MODULE_DATABASE_BANNED 0x0030021 //被禁用
+#define ERROR_AUTHORIZE_MODULE_DATABASE_NOTFOUND 0x0030022 //没有找到
\ No newline at end of file
diff --git a/XEngine_Source/AuthorizeModule_Database/pch.cpp b/XEngine_Source/AuthorizeModule_Database/pch.cpp
index d3d4554..b0769cf 100644
--- a/XEngine_Source/AuthorizeModule_Database/pch.cpp
+++ b/XEngine_Source/AuthorizeModule_Database/pch.cpp
@@ -163,6 +163,14 @@ extern "C" bool DBModule_SQLite_OAuthList(AUTHREG_OAUTHINFO*** pppSt_OAuthInfo,
{
return m_DBSQLite.DBModule_SQLite_OAuthList(pppSt_OAuthInfo, pInt_ListCount);
}
+extern "C" bool DBModule_SQLite_OAuthUPDate(AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ return m_DBSQLite.DBModule_SQLite_OAuthUPDate(pSt_OAuthInfo);
+}
+extern "C" bool DBModule_SQLite_OAuthQuery(AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ return m_DBSQLite.DBModule_SQLite_OAuthQuery(pSt_OAuthInfo);
+}
/************************************************************************/
/* MYSQL数据库服务导出函数 */
/************************************************************************/
@@ -297,4 +305,12 @@ extern "C" bool DBModule_MySQL_OAuthDelete(AUTHREG_OAUTHINFO* pSt_OAuthInfo)
extern "C" bool DBModule_MySQL_OAuthList(AUTHREG_OAUTHINFO*** pppSt_OAuthInfo, int* pInt_ListCount)
{
return m_DBMySQL.DBModule_MySQL_OAuthList(pppSt_OAuthInfo, pInt_ListCount);
+}
+extern "C" bool DBModule_MySQL_OAuthUPDate(AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ return m_DBMySQL.DBModule_MySQL_OAuthUPDate(pSt_OAuthInfo);
+}
+extern "C" bool DBModule_MySQL_OAuthQuery(AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ return m_DBMySQL.DBModule_MySQL_OAuthQuery(pSt_OAuthInfo);
}
\ No newline at end of file
diff --git a/XEngine_Source/AuthorizeModule_Protocol/AuthorizeModule_Protocol.def b/XEngine_Source/AuthorizeModule_Protocol/AuthorizeModule_Protocol.def
index 7bf62bf..d579d06 100644
--- a/XEngine_Source/AuthorizeModule_Protocol/AuthorizeModule_Protocol.def
+++ b/XEngine_Source/AuthorizeModule_Protocol/AuthorizeModule_Protocol.def
@@ -17,6 +17,7 @@ EXPORTS
Protocol_Packet_HttpAnnouncement
Protocol_Packet_HttpTryList
Protocol_Packet_HttpOAuth
+ Protocol_Packet_HttpOAuth2
Protocol_Parse_WSHdr
Protocol_Parse_HttpParseToken
diff --git a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Define.h b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Define.h
index 9ad1abc..ebae8ad 100644
--- a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Define.h
+++ b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Define.h
@@ -423,6 +423,30 @@ extern "C" bool Protocol_Packet_HttpTryList(XCHAR* ptszMsgBuffer, int* pInt_MsgL
备注:
*********************************************************************/
extern "C" bool Protocol_Packet_HttpOAuth(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, AUTHREG_OAUTHINFO* pSt_OAuthInfo);
+/********************************************************************
+函数名称:Protocol_Packet_HttpOAuth2
+函数功能:打包标准的OAuth信息
+ 参数.一:ptszMsgBuffer
+ In/Out:Out
+ 类型:字符指针
+ 可空:N
+ 意思:导出包装好的缓冲区
+ 参数.二:pInt_MsgLen
+ In/Out:Out
+ 类型:整数型指针
+ 可空:N
+ 意思:输出包装大小
+ 参数.三:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:输入要打包的信息
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+extern "C" bool Protocol_Packet_HttpOAuth2(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, AUTHREG_OAUTHINFO* pSt_OAuthInfo);
/************************************************************************/
/* 解析类协议 */
/************************************************************************/
diff --git a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp
index 608cb69..0af0654 100644
--- a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp
+++ b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp
@@ -1008,12 +1008,64 @@ bool CProtocol_Packet::Protocol_Packet_HttpOAuth(XCHAR* ptszMsgBuffer, int* pInt
st_JsonOAuth["tszClientID"] = pSt_OAuthInfo->tszClientID;
st_JsonOAuth["tszClientKey"] = pSt_OAuthInfo->tszClientKey;
st_JsonOAuth["tszUserName"] = pSt_OAuthInfo->tszUserName;
- st_JsonOAuth["tszExpirationTime"] = pSt_OAuthInfo->tszExpirationTime;
+ st_JsonOAuth["nExpirationTime"] = pSt_OAuthInfo->nExpirationTime;
st_JsonRoot["msg"] = "success";
st_JsonRoot["code"] = 0;
st_JsonRoot["st_OAuthInfo"] = st_JsonOAuth;
+ *pInt_MsgLen = st_JsonRoot.toStyledString().length();
+ memcpy(ptszMsgBuffer, st_JsonRoot.toStyledString().c_str(), *pInt_MsgLen);
+ return true;
+}
+/********************************************************************
+函数名称:Protocol_Packet_HttpOAuth2
+函数功能:打包标准的OAuth信息
+ 参数.一:ptszMsgBuffer
+ In/Out:Out
+ 类型:字符指针
+ 可空:N
+ 意思:导出包装好的缓冲区
+ 参数.二:pInt_MsgLen
+ In/Out:Out
+ 类型:整数型指针
+ 可空:N
+ 意思:输出包装大小
+ 参数.三:pSt_OAuthInfo
+ In/Out:In
+ 类型:数据结构指针
+ 可空:N
+ 意思:输入要打包的信息
+返回值
+ 类型:逻辑型
+ 意思:是否成功
+备注:
+*********************************************************************/
+bool CProtocol_Packet::Protocol_Packet_HttpOAuth2(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ Protocol_IsErrorOccur = false;
+
+ if ((NULL == ptszMsgBuffer) || (NULL == pInt_MsgLen))
+ {
+ Protocol_IsErrorOccur = true;
+ Protocol_dwErrorCode = ERROR_AUTHORIZE_MODULE_PROTOCOL_PARAMENT;
+ return false;
+ }
+ Protocol_IsErrorOccur = false;
+
+ if ((NULL == ptszMsgBuffer) || (NULL == pInt_MsgLen))
+ {
+ Protocol_IsErrorOccur = true;
+ Protocol_dwErrorCode = ERROR_AUTHORIZE_MODULE_PROTOCOL_PARAMENT;
+ return false;
+ }
+ Json::Value st_JsonRoot;
+
+ st_JsonRoot["access_token"] = pSt_OAuthInfo->tszTokenStr;
+ st_JsonRoot["refresh_token"] = pSt_OAuthInfo->tszUPToken;
+ st_JsonRoot["token_type"] = "Bearer";
+ st_JsonRoot["expires_in"] = pSt_OAuthInfo->nExpirationTime;
+
*pInt_MsgLen = st_JsonRoot.toStyledString().length();
memcpy(ptszMsgBuffer, st_JsonRoot.toStyledString().c_str(), *pInt_MsgLen);
return true;
diff --git a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.h b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.h
index 14fbfb2..99b81f4 100644
--- a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.h
+++ b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.h
@@ -32,6 +32,7 @@ class CProtocol_Packet
bool Protocol_Packet_HttpAnnouncement(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, AUTHREG_ANNOUNCEMENT*** pppSt_Announcement, int nListCount);
bool Protocol_Packet_HttpTryList(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, AUTHREG_TEMPVER*** pppSt_TryList, int nListCount);
bool Protocol_Packet_HttpOAuth(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, AUTHREG_OAUTHINFO* pSt_OAuthInfo);
+ bool Protocol_Packet_HttpOAuth2(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, AUTHREG_OAUTHINFO* pSt_OAuthInfo);
protected:
private:
};
\ No newline at end of file
diff --git a/XEngine_Source/AuthorizeModule_Protocol/pch.cpp b/XEngine_Source/AuthorizeModule_Protocol/pch.cpp
index 4598f30..981604f 100644
--- a/XEngine_Source/AuthorizeModule_Protocol/pch.cpp
+++ b/XEngine_Source/AuthorizeModule_Protocol/pch.cpp
@@ -87,6 +87,10 @@ extern "C" bool Protocol_Packet_HttpOAuth(XCHAR* ptszMsgBuffer, int* pInt_MsgLen
{
return m_ProtocolPacket.Protocol_Packet_HttpOAuth(ptszMsgBuffer, pInt_MsgLen, pSt_OAuthInfo);
}
+extern "C" bool Protocol_Packet_HttpOAuth2(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, AUTHREG_OAUTHINFO* pSt_OAuthInfo)
+{
+ return m_ProtocolPacket.Protocol_Packet_HttpOAuth2(ptszMsgBuffer, pInt_MsgLen, pSt_OAuthInfo);
+}
/************************************************************************/
/* 解析类协议 */
/************************************************************************/
diff --git a/XEngine_Source/XAuth_Protocol.h b/XEngine_Source/XAuth_Protocol.h
index d0a354a..ab83e2f 100644
--- a/XEngine_Source/XAuth_Protocol.h
+++ b/XEngine_Source/XAuth_Protocol.h
@@ -129,8 +129,9 @@ typedef struct
{
XCHAR tszUserName[128]; //用户名
XCHAR tszTokenStr[128]; //Token
+ XCHAR tszUPToken[128]; //Token
XCHAR tszClientID[128]; //ID
XCHAR tszClientKey[128]; //秘钥
XCHAR tszCreateTime[64]; //创建时间
- XCHAR tszExpirationTime[64]; //过期时间
+ int nExpirationTime; //过期时间
}AUTHREG_OAUTHINFO;
\ No newline at end of file
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp
index 3ca8d55..b52cb33 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp
@@ -162,13 +162,7 @@ bool XEngine_AuthorizeHTTP_Token(LPCXSTR lpszClientAddr, XCHAR** pptszList, int
XENGINE_LIBTIME st_LibTime = {};
_tcsxcpy(st_OAuthInfo.tszUserName, st_UserInfo.tszUserName);
- if (nListCount > 2)
- {
- time_t nTime = time(NULL) + _ttxoi(tszTimeout);
- BaseLib_Time_TTimeToStuTime(nTime, &st_LibTime);
- BaseLib_Time_TimeToStr(st_OAuthInfo.tszExpirationTime, NULL, true, &st_LibTime);
- }
-
+ st_OAuthInfo.nExpirationTime = _ttxoi(tszTimeout);
BaseLib_Handle_CreateStr(st_OAuthInfo.tszClientID, 16, 1);
BaseLib_Handle_CreateStr(st_OAuthInfo.tszClientKey);
BaseLib_Time_TimeToStr(st_OAuthInfo.tszCreateTime);
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp
new file mode 100644
index 0000000..cfb370e
--- /dev/null
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp
@@ -0,0 +1,62 @@
+#include "../Authorize_Hdr.h"
+
+bool XEngine_AuthorizeHTTP_OAuth(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, LPCXSTR lpszMSGBuffer, int nMSGLen)
+{
+ int nSDLen = 4096;
+ XCHAR tszSDBuffer[4096] = {};
+ XCHAR tszURLKey[128] = {};
+ XCHAR tszURLValue[128] = {};
+ LPCXSTR lpszAPICreate = _X("create");
+ LPCXSTR lpszAPIUPDate = _X("update");
+ LPCXSTR lpszAPIClose = _X("close");
+
+ if (0 == _tcsxncmp(lpszAPICreate, lpszAPIName, _tcsxlen(lpszAPICreate)))
+ {
+ //http://app.xyry.org:5302/api/oauth/create
+ VERIFICATION_OAUTHINFO st_VerificationInfo = {};
+ AUTHREG_OAUTHINFO st_OAuthInfo = {};
+
+ Verification_OAuth_Parse(&st_VerificationInfo, NULL, lpszMSGBuffer);
+ _tcsxcpy(st_OAuthInfo.tszClientID, st_VerificationInfo.tszClientID);
+ _tcsxcpy(st_OAuthInfo.tszClientKey, st_VerificationInfo.tszClientSecert);
+
+ bool bRet = false;
+ if (0 == st_AuthConfig.st_XSql.nDBType)
+ {
+ bRet = DBModule_SQLite_OAuthQuery(&st_OAuthInfo);
+ }
+ else
+ {
+ bRet = DBModule_MySQL_OAuthQuery(&st_OAuthInfo);
+ }
+ if (!bRet)
+ {
+ Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_REQUEST, "request info is correct,maybe client id or key is incorrect");
+ XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP);
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,请求创建OAuth的TOKEN失败,查询用户信息id:%s key:%s失败:%lX"), lpszClientAddr, st_OAuthInfo.tszClientID, st_OAuthInfo.tszClientKey, DBModule_GetLastError());
+ return false;
+ }
+ BaseLib_Handle_CreateStr(st_OAuthInfo.tszTokenStr, 32);
+ BaseLib_Handle_CreateStr(st_OAuthInfo.tszUPToken, 32);
+ if (0 == st_AuthConfig.st_XSql.nDBType)
+ {
+ bRet = DBModule_SQLite_OAuthUPDate(&st_OAuthInfo);
+ }
+ else
+ {
+ bRet = DBModule_MySQL_OAuthUPDate(&st_OAuthInfo);
+ }
+ if (!bRet)
+ {
+ Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_SERVER, "internal server failure");
+ XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP);
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,请求更新OAuth的TOKEN失败,内部错误:%lX"), lpszClientAddr, DBModule_GetLastError());
+ return false;
+ }
+ Protocol_Packet_HttpOAuth2(tszSDBuffer, &nSDLen, &st_OAuthInfo);
+ XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP);
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s"), lpszClientAddr);
+ }
+
+ return true;
+}
\ No newline at end of file
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.h b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.h
new file mode 100644
index 0000000..c8a4e5f
--- /dev/null
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.h
@@ -0,0 +1,3 @@
+#pragma once
+
+bool XEngine_AuthorizeHTTP_OAuth(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, LPCXSTR lpszMSGBuffer, int nMSGLen);
\ No newline at end of file
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Hdr.h b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Hdr.h
index c36870c..b0108dc 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Hdr.h
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Hdr.h
@@ -111,6 +111,7 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch;
#include "AuthorizeHTTP_Post/AuthorizeHTTP_CDKey.h"
#include "AuthorizeHTTP_Post/AuthorizeHTTP_Announcement.h"
#include "AuthorizeHTTP_Post/AuthorizeHTTP_Try.h"
+#include "AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.h"
#include "AuthorizeHTTP_Get/AuthorizeHTTP_Token.h"
#include "AuthorizeHTTP_Get/AuthorizeHTTP_GetTask.h"
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp
index 7922812..1f07755 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp
@@ -191,7 +191,8 @@ bool XEngine_Client_HttpTask(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int
LPCXSTR lpszAPIVerCDKey = _X("cdkey");
LPCXSTR lpszAPIVerNotice = _X("notice");
LPCXSTR lpszAPIVerTry = _X("try");
-
+ LPCXSTR lpszAPIOAuth = _X("oauth");
+
memset(tszAPIType, '\0', sizeof(tszAPIType));
memset(tszAPIVer, '\0', sizeof(tszAPIVer));
memset(tszAPIName, '\0', sizeof(tszAPIName));
@@ -313,6 +314,10 @@ bool XEngine_Client_HttpTask(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int
{
XEngine_AuthorizeHTTP_User(xhToken, lpszClientAddr, tszAPIName, lpszMsgBuffer, nMsgLen);
}
+ else if (0 == _tcsxncmp(lpszAPIOAuth, tszAPIVer, _tcsxlen(lpszAPIOAuth)))
+ {
+ XEngine_AuthorizeHTTP_OAuth(lpszClientAddr, tszAPIName, lpszMsgBuffer, nMsgLen);
+ }
else
{
Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_REQUEST, "reqeust api is not support");
@@ -330,7 +335,7 @@ bool XEngine_Client_HttpTask(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int
LPCXSTR lpszFuncName = _X("api");
LPCXSTR lpszAPIVerDCode = _X("dcode");
LPCXSTR lpszAPIVerTime = _X("time");
-
+
memset(tszUrlName, '\0', sizeof(tszUrlName));
HttpProtocol_ServerHelp_GetParament(pSt_HTTPParament->tszHttpUri, &pptszList, &nListCount, tszUrlName);
if ((nListCount < 1) || (0 != _tcsxncmp(lpszFuncName, tszUrlName, _tcsxlen(lpszFuncName))))
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Makefile b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Makefile
index b381650..d60d5c5 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Makefile
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Makefile
@@ -10,7 +10,7 @@ LIB = -lXEngine_InfoReport -ljsoncpp -lXEngine_Verification -lXEngine_MSGNotify
-lAuthorizeModule_Session -lAuthorizeModule_Database -lAuthorizeModule_Protocol -lAuthorizeModule_Configure -lAuthorizeModule_Help
LIBEX =
OBJECTS = Authorize_Config.o Authorize_Net.o Authorize_Task.o Authorize_TCPTask.o Authorize_WSTask.o Authorize_HttpTask.o Authorize_MQTTTask.o XEngine_AuthorizeService.o \
- AuthorizeHTTP_Client.o AuthorizeHTTP_Serial.o AuthorizeHTTP_User.o AuthorizeHTTP_Pass.o AuthorizeHTTP_Switch.o AuthorizeHTTP_Banned.o AuthorizeHTTP_CDKey.o AuthorizeHTTP_Announcement.o AuthorizeHTTP_Try.o\
+ AuthorizeHTTP_Client.o AuthorizeHTTP_Serial.o AuthorizeHTTP_User.o AuthorizeHTTP_Pass.o AuthorizeHTTP_Switch.o AuthorizeHTTP_Banned.o AuthorizeHTTP_CDKey.o AuthorizeHTTP_Announcement.o AuthorizeHTTP_Try.o AuthorizeHTTP_OAuth.o \
AuthorizeHTTP_Token.o AuthorizeHTTP_GetTask.o
ifeq ($(RELEASE),1)
@@ -87,6 +87,8 @@ AuthorizeHTTP_Announcement.o:./AuthorizeHTTP_Post/AuthorizeHTTP_Announcement.cpp
$(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(PLATVER) $(LOADHDR) ./AuthorizeHTTP_Post/AuthorizeHTTP_Announcement.cpp
AuthorizeHTTP_Try.o:./AuthorizeHTTP_Post/AuthorizeHTTP_Try.cpp
$(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(PLATVER) $(LOADHDR) ./AuthorizeHTTP_Post/AuthorizeHTTP_Try.cpp
+AuthorizeHTTP_OAuth.o:./AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp
+ $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(PLATVER) $(LOADHDR) ./AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp
AuthorizeHTTP_Token.o:./AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp
$(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(PLATVER) $(LOADHDR) ./AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj
index 48728a9..ff027ba 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj
@@ -238,6 +238,7 @@
+
@@ -259,6 +260,7 @@
+
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj.filters b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj.filters
index ff32cae..93b7304 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj.filters
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj.filters
@@ -84,6 +84,9 @@
源文件
+
+ 源文件\AuthorizeHTTP_Post
+
@@ -146,5 +149,8 @@
头文件
+
+ 头文件\AuthorizeHTTP_Post
+
\ No newline at end of file
From 8721ac87ed229012c3a718dde3f486a2fd2729b0 Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Wed, 19 Aug 2026 15:20:26 +0800
Subject: [PATCH 08/15] added:revoke for auth 2.0
---
.../AuthorizeHTTP_OAuth.cpp | 44 ++++++++++++++++---
.../Authorize_Net.cpp | 17 ++++---
XEngine_Source/XEngine_DependLibrary | 2 +-
3 files changed, 50 insertions(+), 13 deletions(-)
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp
index cfb370e..5745e53 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp
@@ -6,13 +6,13 @@ bool XEngine_AuthorizeHTTP_OAuth(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, LP
XCHAR tszSDBuffer[4096] = {};
XCHAR tszURLKey[128] = {};
XCHAR tszURLValue[128] = {};
- LPCXSTR lpszAPICreate = _X("create");
- LPCXSTR lpszAPIUPDate = _X("update");
- LPCXSTR lpszAPIClose = _X("close");
+ LPCXSTR lpszAPIToken = _X("token"); //更新,创建
+ LPCXSTR lpszAPIRevoke = _X("revoke"); //撤销
+ LPCXSTR lpszAPIIntrospect = _X("introspect"); //检查
- if (0 == _tcsxncmp(lpszAPICreate, lpszAPIName, _tcsxlen(lpszAPICreate)))
+ if (0 == _tcsxncmp(lpszAPIToken, lpszAPIName, _tcsxlen(lpszAPIToken)))
{
- //http://app.xyry.org:5302/api/oauth/create
+ //http://127.0.0.1:5302/api/oauth/token
VERIFICATION_OAUTHINFO st_VerificationInfo = {};
AUTHREG_OAUTHINFO st_OAuthInfo = {};
@@ -50,12 +50,42 @@ bool XEngine_AuthorizeHTTP_OAuth(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, LP
{
Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_SERVER, "internal server failure");
XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP);
- XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,请求更新OAuth的TOKEN失败,内部错误:%lX"), lpszClientAddr, DBModule_GetLastError());
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,请求创建OAuth的TOKEN失败,内部错误:%lX"), lpszClientAddr, DBModule_GetLastError());
return false;
}
Protocol_Packet_HttpOAuth2(tszSDBuffer, &nSDLen, &st_OAuthInfo);
XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP);
- XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s"), lpszClientAddr);
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,请求创建OAuth Token:%s 成功"), lpszClientAddr, st_OAuthInfo.tszTokenStr);
+ }
+ else if (0 == _tcsxncmp(lpszAPIRevoke, lpszAPIName, _tcsxlen(lpszAPIRevoke)))
+ {
+ //http://127.0.0.1:5302/api/oauth/revoke
+ VERIFICATION_OAUTHINFO st_VerificationInfo = {};
+ AUTHREG_OAUTHINFO st_OAuthInfo = {};
+
+ Verification_OAuth_Parse(&st_VerificationInfo, NULL, lpszMSGBuffer);
+ _tcsxcpy(st_OAuthInfo.tszTokenStr, st_VerificationInfo.tszTokenStr);
+
+ bool bRet = false;
+ if (0 == st_AuthConfig.st_XSql.nDBType)
+ {
+ bRet = DBModule_SQLite_OAuthDelete(&st_OAuthInfo);
+ }
+ else
+ {
+ bRet = DBModule_MySQL_OAuthDelete(&st_OAuthInfo);
+ }
+ if (!bRet)
+ {
+ Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_REQUEST, "request info is correct,maybe token is incorrect");
+ XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP);
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,请求删除OAuth的TOKEN失败,可能TOKEN:%s 错误:%lX"), lpszClientAddr, st_OAuthInfo.tszTokenStr, DBModule_GetLastError());
+ return false;
+ }
+
+ Protocol_Packet_HttpOAuth2(tszSDBuffer, &nSDLen, &st_OAuthInfo);
+ XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP);
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,请求撤销删除OAuth的token成功,撤销的token:%s"), lpszClientAddr, st_OAuthInfo.tszTokenStr);
}
return true;
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Net.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Net.cpp
index 3386eed..18a4d8f 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Net.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Net.cpp
@@ -230,15 +230,22 @@ bool XEngine_Client_TaskSend(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int
st_HDRParam.nHttpCode = 200;
st_HDRParam.bIsClose = true;
- if (st_AuthConfig.st_XCrypto.bEnable)
+ if (nMsgLen > 0)
{
- CHttpMemory_PoolEx m_CodecMemory(XENGINE_MEMORY_SIZE_MAX);
- Cryption_Api_CryptEncodec((LPCXBTR)lpszMsgBuffer, (XBYTE*)m_CodecMemory.get(), &nMsgLen, st_AuthConfig.st_XCrypto.tszCryptoKey, (ENUM_XENGINE_CRYPTION_SYMMETRIC)st_AuthConfig.st_XCrypto.nCryptionType);
- HttpProtocol_Server_SendMsgEx(xhHttpPacket, m_HTTPMemory.get(), &nSDSize, &st_HDRParam, m_CodecMemory.get(), nMsgLen);
+ if (st_AuthConfig.st_XCrypto.bEnable)
+ {
+ CHttpMemory_PoolEx m_CodecMemory(XENGINE_MEMORY_SIZE_MAX);
+ Cryption_Api_CryptEncodec((LPCXBTR)lpszMsgBuffer, (XBYTE*)m_CodecMemory.get(), &nMsgLen, st_AuthConfig.st_XCrypto.tszCryptoKey, (ENUM_XENGINE_CRYPTION_SYMMETRIC)st_AuthConfig.st_XCrypto.nCryptionType);
+ HttpProtocol_Server_SendMsgEx(xhHttpPacket, m_HTTPMemory.get(), &nSDSize, &st_HDRParam, m_CodecMemory.get(), nMsgLen);
+ }
+ else
+ {
+ HttpProtocol_Server_SendMsgEx(xhHttpPacket, m_HTTPMemory.get(), &nSDSize, &st_HDRParam, lpszMsgBuffer, nMsgLen);
+ }
}
else
{
- HttpProtocol_Server_SendMsgEx(xhHttpPacket, m_HTTPMemory.get(), &nSDSize, &st_HDRParam, lpszMsgBuffer, nMsgLen);
+ HttpProtocol_Server_SendMsgEx(xhHttpPacket, m_HTTPMemory.get(), &nSDSize, &st_HDRParam);
}
NetCore_TCPXCore_SendEx(xhHttpSocket, lpszClientAddr, m_HTTPMemory.get(), nSDSize);
SocketOpt_HeartBeat_ActiveAddrEx(xhHTTPHeart, lpszClientAddr);
diff --git a/XEngine_Source/XEngine_DependLibrary b/XEngine_Source/XEngine_DependLibrary
index dc73149..2d7f1d3 160000
--- a/XEngine_Source/XEngine_DependLibrary
+++ b/XEngine_Source/XEngine_DependLibrary
@@ -1 +1 @@
-Subproject commit dc73149af8aef839085e1f7ad254aea41f0a2f86
+Subproject commit 2d7f1d3d9111b98d1c9d02efa8d9a28b0931354f
From 00be5e6a7e52534c04cf10dbecd2b19427a476d3 Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Wed, 19 Aug 2026 16:33:07 +0800
Subject: [PATCH 09/15] delete:client user token
---
.../DBModule_MySQL/DBModule_MySQL.cpp | 13 ++-----
.../DBModule_SQLite/DBModule_SQLite.cpp | 10 ++----
.../Authorize_Dialog/Dialog_Modify.cpp | 5 ---
.../Authorize_Dialog/Dialog_User.cpp | 34 +++++++++----------
.../Authorize_Net.cpp | 2 +-
5 files changed, 21 insertions(+), 43 deletions(-)
diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp
index c50ce0a..a845c49 100644
--- a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp
+++ b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp
@@ -123,7 +123,7 @@ bool CDBModule_MySQL::DBModule_MySQL_UserRegister(AUTHREG_USERTABLE* pSt_UserInf
SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_EXIST;
return false;
}
- _xstprintf(tszSQLStatement, _X("INSERT INTO `Authorize_User`(UserName, Password, Token, LeftTime, EmailAddr, HardCode, CardSerialType, PhoneNumber, IDCard, nUserLevel, CountTime, CreateTime) values('%s','%s','0','%s','%s','%s','%d',%lld,%lld,%d,0,NOW())"), pSt_UserInfo->st_UserInfo.tszUserName, pSt_UserInfo->st_UserInfo.tszUserPass, pSt_UserInfo->tszLeftTime, pSt_UserInfo->st_UserInfo.tszEMailAddr, pSt_UserInfo->tszHardCode, pSt_UserInfo->enSerialType, pSt_UserInfo->st_UserInfo.nPhoneNumber, pSt_UserInfo->st_UserInfo.nIDNumber, pSt_UserInfo->st_UserInfo.nUserLevel);
+ _xstprintf(tszSQLStatement, _X("INSERT INTO `Authorize_User`(UserName, Password, LeftTime, EmailAddr, HardCode, CardSerialType, PhoneNumber, IDCard, nUserLevel, CountTime, CreateTime) values('%s','%s','%s','%s','%s','%d',%lld,%lld,%d,0,NOW())"), pSt_UserInfo->st_UserInfo.tszUserName, pSt_UserInfo->st_UserInfo.tszUserPass, pSt_UserInfo->tszLeftTime, pSt_UserInfo->st_UserInfo.tszEMailAddr, pSt_UserInfo->tszHardCode, pSt_UserInfo->enSerialType, pSt_UserInfo->st_UserInfo.nPhoneNumber, pSt_UserInfo->st_UserInfo.nIDNumber, pSt_UserInfo->st_UserInfo.nUserLevel);
if (!DataBase_MySQL_Execute(xhData, tszSQLStatement))
{
SQLPacket_IsErrorOccur = true;
@@ -207,12 +207,6 @@ bool CDBModule_MySQL::DBModule_MySQL_UserQuery(LPCXSTR lpszUserName, AUTHREG_USE
{
_tcsxcpy(pSt_UserInfo->st_UserInfo.tszUserPass, pptszResult[nFliedValue]);
}
- //TOKEN
- nFliedValue++;
- if (NULL != pptszResult[nFliedValue])
- {
- pSt_UserInfo->st_UserInfo.xhToken = _ttxoll(pptszResult[nFliedValue]);
- }
//过期时间
nFliedValue++;
if (NULL != pptszResult[nFliedValue])
@@ -476,7 +470,7 @@ bool CDBModule_MySQL::DBModule_MySQL_UserSet(AUTHREG_USERTABLE* pSt_UserTable)
XCHAR tszSQLStatement[1024]; //SQL语句
memset(tszSQLStatement, '\0', 1024);
- _xstprintf(tszSQLStatement, _X("UPDATE `Authorize_User` SET Password = '%s',Token = '%lld',LeftTime = '%s',EmailAddr = '%s',HardCode = '%s',CardSerialType = '%d',PhoneNumber = '%lld',IDCard = '%lld',nUserLevel = '%d',CountTime = '%lld',CreateTime = '%s' WHERE UserName = '%s'"), pSt_UserTable->st_UserInfo.tszUserPass, pSt_UserTable->st_UserInfo.xhToken, pSt_UserTable->tszLeftTime, pSt_UserTable->st_UserInfo.tszEMailAddr, pSt_UserTable->tszHardCode, pSt_UserTable->enSerialType, pSt_UserTable->st_UserInfo.nPhoneNumber, pSt_UserTable->st_UserInfo.nIDNumber, pSt_UserTable->st_UserInfo.nUserLevel, pSt_UserTable->nTimeCount, pSt_UserTable->st_UserInfo.tszCreateTime, pSt_UserTable->st_UserInfo.tszUserName);
+ _xstprintf(tszSQLStatement, _X("UPDATE `Authorize_User` SET Password = '%s',LeftTime = '%s',EmailAddr = '%s',HardCode = '%s',CardSerialType = '%d',PhoneNumber = '%lld',IDCard = '%lld',nUserLevel = '%d',CountTime = '%lld',CreateTime = '%s' WHERE UserName = '%s'"), pSt_UserTable->st_UserInfo.tszUserPass, pSt_UserTable->tszLeftTime, pSt_UserTable->st_UserInfo.tszEMailAddr, pSt_UserTable->tszHardCode, pSt_UserTable->enSerialType, pSt_UserTable->st_UserInfo.nPhoneNumber, pSt_UserTable->st_UserInfo.nIDNumber, pSt_UserTable->st_UserInfo.nUserLevel, pSt_UserTable->nTimeCount, pSt_UserTable->st_UserInfo.tszCreateTime, pSt_UserTable->st_UserInfo.tszUserName);
//更新用户剩余时间
if (!DataBase_MySQL_Execute(xhData, tszSQLStatement))
@@ -554,9 +548,6 @@ bool CDBModule_MySQL::DBModule_MySQL_UserList(AUTHREG_USERTABLE*** pppSt_UserInf
//密码
nFliedValue++;
_tcsxcpy((*pppSt_UserInfo)[i]->st_UserInfo.tszUserPass, ppszResult[nFliedValue]);
- //TOKEN
- nFliedValue++;
- (*pppSt_UserInfo)[i]->st_UserInfo.xhToken = _ttxoll(ppszResult[nFliedValue]);
//过期时间
nFliedValue++;
_tcsxcpy((*pppSt_UserInfo)[i]->tszLeftTime, ppszResult[nFliedValue]);
diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp
index a4105ed..65afa18 100644
--- a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp
+++ b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp
@@ -126,7 +126,7 @@ bool CDBModule_SQLite::DBModule_SQLite_UserRegister(AUTHREG_USERTABLE* pSt_UserI
SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_EXIST;
return false;
}
- _xstprintf(tszSQLStatement, _X("INSERT INTO Authorize_User(UserName, Password, Token, LeftTime, EmailAddr, HardCode, CardSerialType, PhoneNumber, IDCard, nUserLevel, CountTime, CreateTime) values('%s','%s','0','%s','%s','%s','%d',%lld,%lld,%d,0,datetime('now', 'localtime'))"), pSt_UserInfo->st_UserInfo.tszUserName, pSt_UserInfo->st_UserInfo.tszUserPass, pSt_UserInfo->tszLeftTime, pSt_UserInfo->st_UserInfo.tszEMailAddr, pSt_UserInfo->tszHardCode, pSt_UserInfo->enSerialType, pSt_UserInfo->st_UserInfo.nPhoneNumber, pSt_UserInfo->st_UserInfo.nIDNumber, pSt_UserInfo->st_UserInfo.nUserLevel);
+ _xstprintf(tszSQLStatement, _X("INSERT INTO Authorize_User(UserName, Password, LeftTime, EmailAddr, HardCode, CardSerialType, PhoneNumber, IDCard, nUserLevel, CountTime, CreateTime) values('%s','%s','%s','%s','%s','%d',%lld,%lld,%d,0,datetime('now', 'localtime'))"), pSt_UserInfo->st_UserInfo.tszUserName, pSt_UserInfo->st_UserInfo.tszUserPass, pSt_UserInfo->tszLeftTime, pSt_UserInfo->st_UserInfo.tszEMailAddr, pSt_UserInfo->tszHardCode, pSt_UserInfo->enSerialType, pSt_UserInfo->st_UserInfo.nPhoneNumber, pSt_UserInfo->st_UserInfo.nIDNumber, pSt_UserInfo->st_UserInfo.nUserLevel);
if (!DataBase_SQLite_Exec(xhData, tszSQLStatement))
{
SQLPacket_IsErrorOccur = true;
@@ -201,9 +201,6 @@ bool CDBModule_SQLite::DBModule_SQLite_UserQuery(LPCXSTR lpszUserName, AUTHREG_U
//密码
nFliedValue++;
_tcsxcpy(pSt_UserInfo->st_UserInfo.tszUserPass, ppszResult[nFliedValue]);
- //TOKEN
- nFliedValue++;
- pSt_UserInfo->st_UserInfo.xhToken = _ttxoll(ppszResult[nFliedValue]);
//过期时间
nFliedValue++;
_tcsxcpy(pSt_UserInfo->tszLeftTime, ppszResult[nFliedValue]);
@@ -433,7 +430,7 @@ bool CDBModule_SQLite::DBModule_SQLite_UserSet(AUTHREG_USERTABLE* pSt_UserTable)
XCHAR tszSQLStatement[1024]; //SQL语句
memset(tszSQLStatement, '\0', 1024);
- _xstprintf(tszSQLStatement, _X("UPDATE Authorize_User SET Password = '%s',Token = '%lld',LeftTime = '%s',EmailAddr = '%s',HardCode = '%s',CardSerialType = '%d',PhoneNumber = '%lld',IDCard = '%lld',nUserLevel = '%d',CountTime = '%lld',CreateTime = '%s' WHERE UserName = '%s'"), pSt_UserTable->st_UserInfo.tszUserPass, pSt_UserTable->st_UserInfo.xhToken, pSt_UserTable->tszLeftTime, pSt_UserTable->st_UserInfo.tszEMailAddr, pSt_UserTable->tszHardCode, pSt_UserTable->enSerialType, pSt_UserTable->st_UserInfo.nPhoneNumber, pSt_UserTable->st_UserInfo.nIDNumber, pSt_UserTable->st_UserInfo.nUserLevel, pSt_UserTable->nTimeCount, pSt_UserTable->st_UserInfo.tszCreateTime, pSt_UserTable->st_UserInfo.tszUserName);
+ _xstprintf(tszSQLStatement, _X("UPDATE Authorize_User SET Password = '%s',LeftTime = '%s',EmailAddr = '%s',HardCode = '%s',CardSerialType = '%d',PhoneNumber = '%lld',IDCard = '%lld',nUserLevel = '%d',CountTime = '%lld',CreateTime = '%s' WHERE UserName = '%s'"), pSt_UserTable->st_UserInfo.tszUserPass, pSt_UserTable->tszLeftTime, pSt_UserTable->st_UserInfo.tszEMailAddr, pSt_UserTable->tszHardCode, pSt_UserTable->enSerialType, pSt_UserTable->st_UserInfo.nPhoneNumber, pSt_UserTable->st_UserInfo.nIDNumber, pSt_UserTable->st_UserInfo.nUserLevel, pSt_UserTable->nTimeCount, pSt_UserTable->st_UserInfo.tszCreateTime, pSt_UserTable->st_UserInfo.tszUserName);
//更新用户剩余时间
if (!DataBase_SQLite_Exec(xhData, tszSQLStatement))
{
@@ -506,9 +503,6 @@ bool CDBModule_SQLite::DBModule_SQLite_UserList(AUTHREG_USERTABLE*** pppSt_UserI
//密码
nFliedValue++;
_tcsxcpy((*pppSt_UserInfo)[i]->st_UserInfo.tszUserPass, ppszResult[nFliedValue]);
- //TOKEN
- nFliedValue++;
- (*pppSt_UserInfo)[i]->st_UserInfo.xhToken = _ttxoll(ppszResult[nFliedValue]);
//过期时间
nFliedValue++;
_tcsxcpy((*pppSt_UserInfo)[i]->tszLeftTime, ppszResult[nFliedValue]);
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.cpp
index 9110928..0af111f 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.cpp
@@ -141,7 +141,6 @@ BOOL CDialog_Modify::OnInitDialog()
m_EditUser.SetWindowText(A2W(st_JsonObject["st_UserInfo"]["tszUserName"].asCString()));
m_EditPass.SetWindowText(A2W(st_JsonObject["st_UserInfo"]["tszUserPass"].asCString()));
m_EditEMail.SetWindowText(A2W(st_JsonObject["st_UserInfo"]["tszEMailAddr"].asCString()));
- m_EditUserToken.SetWindowText(std::to_wstring(st_JsonObject["st_UserInfo"]["xhToken"].asInt64()).c_str());
m_EditCountTime.SetWindowText(std::to_wstring(st_JsonObject["st_UserInfo"]["nTimeCount"].asInt64()).c_str());
COleDateTime m_OleDTime;
if (m_OleDTime.ParseDateTime(A2W(st_JsonObject["st_UserInfo"]["tszCreateTime"].asCString())))
@@ -187,9 +186,6 @@ void CDialog_Modify::OnBnClickedButton2()
m_EditPass.GetWindowText(m_StrUserInfo);
strcpy(st_UserTable.st_UserInfo.tszUserPass, W2A(m_StrUserInfo.GetBuffer()));
m_StrUserInfo.ReleaseBuffer();
- m_EditUserToken.GetWindowText(m_StrUserInfo);
- st_UserTable.st_UserInfo.xhToken = _ttxoll(W2A(m_StrUserInfo.GetBuffer()));
- m_StrUserInfo.ReleaseBuffer();
m_EditCountTime.GetWindowText(m_StrUserInfo);
st_UserTable.nTimeCount = _ttxoll(W2A(m_StrUserInfo.GetBuffer()));
m_StrUserInfo.ReleaseBuffer();
@@ -244,7 +240,6 @@ void CDialog_Modify::OnBnClickedButton2()
st_JsonUser["tszUserName"] = st_UserTable.st_UserInfo.tszUserName;
st_JsonUser["tszUserPass"] = st_UserTable.st_UserInfo.tszUserPass;
- st_JsonUser["xhToken"] = st_UserTable.st_UserInfo.xhToken;
st_JsonUser["tszEMailAddr"] = st_UserTable.st_UserInfo.tszEMailAddr;
st_JsonUser["tszCreateTime"] = st_UserTable.st_UserInfo.tszCreateTime;
st_JsonUser["nPhoneNumber"] = st_UserTable.st_UserInfo.nPhoneNumber;
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_User.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_User.cpp
index fa59667..7f4b564 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_User.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_User.cpp
@@ -55,15 +55,14 @@ BOOL CDialog_User::OnInitDialog()
// TODO: 在此添加额外的初始化
m_ListCtrlClient.InsertColumn(0, _T("序号"), LVCFMT_LEFT, 40);
m_ListCtrlClient.InsertColumn(1, _T("用户名"), LVCFMT_LEFT, 120);
- m_ListCtrlClient.InsertColumn(2, _T("TOKEN"), LVCFMT_LEFT, 60);
- m_ListCtrlClient.InsertColumn(3, _T("IP地址"), LVCFMT_LEFT, 100);
- m_ListCtrlClient.InsertColumn(4, _T("级别"), LVCFMT_LEFT, 80);
- m_ListCtrlClient.InsertColumn(5, _T("在线时间(秒钟)"), LVCFMT_LEFT, 150);
- m_ListCtrlClient.InsertColumn(6, _T("剩余时间/过期时间"), LVCFMT_LEFT, 150);
- m_ListCtrlClient.InsertColumn(7, _T("充值类型"), LVCFMT_LEFT, 80);
- m_ListCtrlClient.InsertColumn(8, _T("设备类型"), LVCFMT_LEFT, 80);
- m_ListCtrlClient.InsertColumn(9, _T("是否在线"), LVCFMT_LEFT, 80);
- m_ListCtrlClient.InsertColumn(10, _T("总在线时长"), LVCFMT_LEFT, 80);
+ m_ListCtrlClient.InsertColumn(2, _T("IP地址"), LVCFMT_LEFT, 100);
+ m_ListCtrlClient.InsertColumn(3, _T("级别"), LVCFMT_LEFT, 80);
+ m_ListCtrlClient.InsertColumn(4, _T("在线时间(秒钟)"), LVCFMT_LEFT, 150);
+ m_ListCtrlClient.InsertColumn(5, _T("剩余时间/过期时间"), LVCFMT_LEFT, 150);
+ m_ListCtrlClient.InsertColumn(6, _T("充值类型"), LVCFMT_LEFT, 80);
+ m_ListCtrlClient.InsertColumn(7, _T("设备类型"), LVCFMT_LEFT, 80);
+ m_ListCtrlClient.InsertColumn(8, _T("是否在线"), LVCFMT_LEFT, 80);
+ m_ListCtrlClient.InsertColumn(9, _T("总在线时长"), LVCFMT_LEFT, 80);
m_ListCtrlClient.SetExtendedStyle(LVS_EX_FULLROWSELECT);
m_EditFlushTime.SetWindowText(_T("10"));
@@ -157,12 +156,11 @@ void CDialog_User::OnBnClickedButton1()
m_ListCtrlClient.InsertItem(i, _T(""));
m_ListCtrlClient.SetItemText(i, 0, tszIndex);
m_ListCtrlClient.SetItemText(i, 1, A2W(st_JsonObject["tszUserName"].asCString()));
- m_ListCtrlClient.SetItemText(i, 2, std::to_wstring(st_JsonObject["xhToken"].asInt64()).c_str());
if (!st_JsonArray["tszClientAddr"].isNull())
{
- m_ListCtrlClient.SetItemText(i, 3, A2W(st_JsonArray["tszClientAddr"].asCString()));
+ m_ListCtrlClient.SetItemText(i, 2, A2W(st_JsonArray["tszClientAddr"].asCString()));
}
- m_ListCtrlClient.SetItemText(i, 4, A2W(lpszXLevelType[st_JsonObject["nUserLevel"].asInt() + 1]));
+ m_ListCtrlClient.SetItemText(i, 3, A2W(lpszXLevelType[st_JsonObject["nUserLevel"].asInt() + 1]));
if (1 == st_JsonObject["nUserState"].asInt())
{
@@ -171,13 +169,13 @@ void CDialog_User::OnBnClickedButton1()
__int64x nTime = st_JsonArray["nOnlineTime"].asUInt64();
_stprintf(tszTimeStr, _T("%lld"), nTime);
- m_ListCtrlClient.SetItemText(i, 5, tszTimeStr);
+ m_ListCtrlClient.SetItemText(i, 4, tszTimeStr);
}
- m_ListCtrlClient.SetItemText(i, 6, A2W(st_JsonArray["tszLeftTime"].asCString()));
- m_ListCtrlClient.SetItemText(i, 7, A2W(lpszXSerialType[st_JsonArray["enSerialType"].asInt()]));
- m_ListCtrlClient.SetItemText(i, 8, A2W(lpszXDevType[st_JsonArray["enDeviceType"].asInt()]));
- m_ListCtrlClient.SetItemText(i, 9, lpszStuType[st_JsonObject["nUserState"].asInt()]);
- m_ListCtrlClient.SetItemText(i, 10, std::to_wstring(st_JsonObject["nTimeCount"].asInt64()).c_str());
+ m_ListCtrlClient.SetItemText(i, 5, A2W(st_JsonArray["tszLeftTime"].asCString()));
+ m_ListCtrlClient.SetItemText(i, 6, A2W(lpszXSerialType[st_JsonArray["enSerialType"].asInt()]));
+ m_ListCtrlClient.SetItemText(i, 7, A2W(lpszXDevType[st_JsonArray["enDeviceType"].asInt()]));
+ m_ListCtrlClient.SetItemText(i, 8, lpszStuType[st_JsonObject["nUserState"].asInt()]);
+ m_ListCtrlClient.SetItemText(i, 9, std::to_wstring(st_JsonObject["nTimeCount"].asInt64()).c_str());
}
BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMsgBuffer);
UpdateWindow();
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Net.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Net.cpp
index 18a4d8f..25ec5e8 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Net.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Net.cpp
@@ -73,7 +73,7 @@ bool XCALLBACK XEngine_Client_HttpAccept(LPCXSTR lpszClientAddr, XSOCKET hSocket
}
void XCALLBACK XEngine_Client_HttpRecv(LPCXSTR lpszClientAddr, XSOCKET hSocket, LPCXSTR lpszRecvMsg, int nMsgLen, XPVOID lParam)
{
- if (!HttpProtocol_Server_InserQueueEx(xhHttpPacket, lpszClientAddr, lpszRecvMsg, nMsgLen))
+ if (!HttpProtocol_Server_InsertQueueEx(xhHttpPacket, lpszClientAddr, lpszRecvMsg, nMsgLen))
{
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,投递数据包失败,大小:%d,错误:%lX"), lpszClientAddr, nMsgLen, Packets_GetLastError());
}
From 06be5baa81a5466637a6e9e5cf69842c83755ce6 Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Wed, 19 Aug 2026 16:42:35 +0800
Subject: [PATCH 10/15] modify:fresh token support for oauth
---
.../AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp
index 5745e53..14e8d86 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp
@@ -15,11 +15,14 @@ bool XEngine_AuthorizeHTTP_OAuth(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, LP
//http://127.0.0.1:5302/api/oauth/token
VERIFICATION_OAUTHINFO st_VerificationInfo = {};
AUTHREG_OAUTHINFO st_OAuthInfo = {};
+ XCHAR tszFreshToken[XPATH_MIN] = {};
Verification_OAuth_Parse(&st_VerificationInfo, NULL, lpszMSGBuffer);
_tcsxcpy(st_OAuthInfo.tszClientID, st_VerificationInfo.tszClientID);
_tcsxcpy(st_OAuthInfo.tszClientKey, st_VerificationInfo.tszClientSecert);
+ _tcsxcpy(tszFreshToken, st_VerificationInfo.tszClientRefresh);
+
bool bRet = false;
if (0 == st_AuthConfig.st_XSql.nDBType)
{
@@ -36,6 +39,18 @@ bool XEngine_AuthorizeHTTP_OAuth(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, LP
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,请求创建OAuth的TOKEN失败,查询用户信息id:%s key:%s失败:%lX"), lpszClientAddr, st_OAuthInfo.tszClientID, st_OAuthInfo.tszClientKey, DBModule_GetLastError());
return false;
}
+ //是否为刷新TOKEN
+ if (_tcsxlen(tszFreshToken) > 0)
+ {
+ //如果是
+ if (0 == _tcsxnicmp(tszFreshToken, st_VerificationInfo.tszClientRefresh, _tcsxlen(st_VerificationInfo.tszClientRefresh)))
+ {
+ Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_UNAUTHORIZE, "token verification failure");
+ XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP);
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,请求刷新OAuth的TOKEN失败,查询用户fresh:%s token:%s 不匹配"), lpszClientAddr, tszFreshToken, st_VerificationInfo.tszClientRefresh);
+ return false;
+ }
+ }
BaseLib_Handle_CreateStr(st_OAuthInfo.tszTokenStr, 32);
BaseLib_Handle_CreateStr(st_OAuthInfo.tszUPToken, 32);
if (0 == st_AuthConfig.st_XSql.nDBType)
From 446f009b3e5a483a430308e83e4817e99fbd72de Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Wed, 19 Aug 2026 20:50:50 +0800
Subject: [PATCH 11/15] added:insert session management for oauth token
---
.../AuthorizeModule_Configure/Config_Define.h | 1 +
.../ModuleConfigure_Json.cpp | 1 +
.../AuthorizeHTTP_OAuth.cpp | 12 ++++
.../Authorize_Task.cpp | 8 ++-
.../XEngine_AuthorizeService.cpp | 56 ++++++++++++++++++-
5 files changed, 73 insertions(+), 5 deletions(-)
diff --git a/XEngine_Source/AuthorizeModule_Configure/Config_Define.h b/XEngine_Source/AuthorizeModule_Configure/Config_Define.h
index 59dbbb1..545c455 100644
--- a/XEngine_Source/AuthorizeModule_Configure/Config_Define.h
+++ b/XEngine_Source/AuthorizeModule_Configure/Config_Define.h
@@ -161,6 +161,7 @@ typedef struct
bool bSwitchBanned; //黑名单
bool bSwitchTokenLogin; //TOKEN开关
bool bSwitchHCLogin; //硬件码登录
+ bool bSwitchOAuth; //是否启用OAuth
bool bSwitchHWBind; //硬件码绑定
}XENGINE_FUNCTIONSWITCH;
//////////////////////////////////////////////////////////////////////////
diff --git a/XEngine_Source/AuthorizeModule_Configure/ModuleConfigure_Json/ModuleConfigure_Json.cpp b/XEngine_Source/AuthorizeModule_Configure/ModuleConfigure_Json/ModuleConfigure_Json.cpp
index 3039b57..47d6953 100644
--- a/XEngine_Source/AuthorizeModule_Configure/ModuleConfigure_Json/ModuleConfigure_Json.cpp
+++ b/XEngine_Source/AuthorizeModule_Configure/ModuleConfigure_Json/ModuleConfigure_Json.cpp
@@ -376,6 +376,7 @@ bool CModuleConfigure_Json::ModuleConfigure_Json_Switch(LPCXSTR lpszConfigFile,
pSt_ServerConfig->bSwitchBanned = st_JsonRoot["bSwitchBanned"].asBool();
pSt_ServerConfig->bSwitchTokenLogin = st_JsonRoot["bSwitchTokenLogin"].asBool();
pSt_ServerConfig->bSwitchHCLogin = st_JsonRoot["bSwitchHCLogin"].asBool();
+ pSt_ServerConfig->bSwitchOAuth = st_JsonRoot["bSwitchOAuth"].asBool();
pSt_ServerConfig->bSwitchHWBind = st_JsonRoot["bSwitchHWBind"].asBool();
return true;
}
\ No newline at end of file
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp
index 14e8d86..f0424f0 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp
@@ -68,6 +68,18 @@ bool XEngine_AuthorizeHTTP_OAuth(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, LP
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,请求创建OAuth的TOKEN失败,内部错误:%lX"), lpszClientAddr, DBModule_GetLastError());
return false;
}
+
+ AUTHREG_USERTABLE st_UserTable = {};
+ if (0 == st_AuthConfig.st_XSql.nDBType)
+ {
+ DBModule_SQLite_UserQuery(st_OAuthInfo.tszUserName, &st_UserTable);
+ }
+ else
+ {
+ DBModule_SQLite_UserQuery(st_OAuthInfo.tszUserName, &st_UserTable);
+ }
+ Session_Token_InsertStr(st_OAuthInfo.tszUserName, &st_UserTable.st_UserInfo, st_OAuthInfo.nExpirationTime);
+
Protocol_Packet_HttpOAuth2(tszSDBuffer, &nSDLen, &st_OAuthInfo);
XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,请求创建OAuth Token:%s 成功"), lpszClientAddr, st_OAuthInfo.tszTokenStr);
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.cpp
index 1917b6e..76c9051 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.cpp
@@ -86,9 +86,13 @@ void XCALLBACK XEngine_TaskEvent_Token(LPCXSTR lpszTokenStr, int nTimeout, int n
}
}
- if (bRemove)
+ AUTHREG_OAUTHINFO st_OAuthInfo = {};
+ _tcsxcpy(st_OAuthInfo.tszTokenStr, lpszTokenStr);
+ bool bRet = DBModule_SQLite_OAuthDelete(&st_OAuthInfo);
+
+ if (bRemove || bRet)
{
Session_Token_DeleteStr(lpszTokenStr);
- XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("Token:%s,用户名:%s,已经超时,权限级别:%d,被移除服务器"), lpszTokenStr, st_UserInfo.tszUserName, st_UserInfo.nUserLevel);
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("Token:%s,用户名:%s,已经超时,权限级别:%d,被移除服务器,移除类型:%s"), lpszTokenStr, st_UserInfo.tszUserName, st_UserInfo.nUserLevel, bRet ? "普通" : "OAuth");
}
}
\ No newline at end of file
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp
index c4010b5..0e29f24 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp
@@ -160,16 +160,17 @@ int main(int argc, char** argv)
#endif
bIsRun = true;
int nRet = -1;
- HELPCOMPONENTS_XLOG_CONFIGURE st_XLogConfig;
+ int nListOAuth = 0;
+ AUTHREG_OAUTHINFO** ppSt_OAuthInfo;
THREADPOOL_PARAMENT** ppSt_ListTCPThread;
THREADPOOL_PARAMENT** ppSt_ListWSThread;
THREADPOOL_PARAMENT** ppSt_ListHttpThread;
THREADPOOL_PARAMENT** ppSt_ListMQTTParam;
+ HELPCOMPONENTS_XLOG_CONFIGURE st_XLogConfig = {};
LPCXSTR lpszHTTPMime = _X("./XEngine_Config/HttpMime.types");
LPCXSTR lpszHTTPCode = _X("./XEngine_Config/HttpCode.types");
- memset(&st_XLogConfig, '\0', sizeof(HELPCOMPONENTS_XLOG_CONFIGURE));
memset(&st_AuthConfig, '\0', sizeof(XENGINE_SERVICECONFIG));
memset(&st_FunSwitch, '\0', sizeof(XENGINE_FUNCTIONSWITCH));
@@ -463,6 +464,53 @@ int main(int argc, char** argv)
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,加密传输设置为关闭,采用明文传输"));
}
+ if (0 == st_AuthConfig.st_XSql.nDBType)
+ {
+ DBModule_SQLite_OAuthList(&ppSt_OAuthInfo, &nListOAuth);
+ }
+ else
+ {
+ DBModule_MySQL_OAuthList(&ppSt_OAuthInfo, &nListOAuth);
+ }
+ for (int i = 0; i < nListOAuth; i++)
+ {
+ //是否过期
+ time_t nTimeCreate = 0;
+ XENGINE_LIBTIME st_LibTime = {};
+ BaseLib_Time_StrToTime(ppSt_OAuthInfo[i]->tszCreateTime, &st_LibTime);
+ BaseLib_Time_StuTimeToTTime(&st_LibTime, &nTimeCreate);
+
+ time_t nTimeStop = time(NULL);
+ if ((ppSt_OAuthInfo[i]->nExpirationTime + nTimeCreate) - nTimeStop > 0)
+ {
+ AUTHREG_USERTABLE st_UserTable = {};
+ if (0 == st_AuthConfig.st_XSql.nDBType)
+ {
+ DBModule_SQLite_UserQuery(ppSt_OAuthInfo[i]->tszUserName, &st_UserTable);
+ }
+ else
+ {
+ DBModule_SQLite_UserQuery(ppSt_OAuthInfo[i]->tszUserName, &st_UserTable);
+ }
+ //剩余时间
+ int nTimeLeft = nTimeStop - (ppSt_OAuthInfo[i]->nExpirationTime + nTimeCreate);
+ Session_Token_InsertStr(ppSt_OAuthInfo[i]->tszUserName, &st_UserTable.st_UserInfo, nTimeLeft);
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,用户:%s 绑定TOKEN:%s ,插入会话管理器"), st_UserTable.st_UserInfo.tszUserName, ppSt_OAuthInfo[i]->tszTokenStr);
+ }
+ else
+ {
+ if (0 == st_AuthConfig.st_XSql.nDBType)
+ {
+ DBModule_SQLite_OAuthDelete(ppSt_OAuthInfo[i]);
+ }
+ else
+ {
+ DBModule_MySQL_OAuthDelete(ppSt_OAuthInfo[i]);
+ }
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_WARN, _X("启动服务中,检查用户:%s 绑定TOKEN:%s 过期,删除"), ppSt_OAuthInfo[i]->tszUserName, ppSt_OAuthInfo[i]->tszTokenStr);
+ }
+ }
+
if (0 == _xtaccess(st_AuthConfig.st_XVerification.st_XCDKey.tszKeyFile, 0))
{
VERIFICATION_XAUTHKEY st_AuthLocal = {};
@@ -482,6 +530,7 @@ int main(int argc, char** argv)
{
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_WARN, _X("启动服务中,授权文件验证失败,授权文件没有找到"));
}
+
#ifndef _DEBUG
//发送信息报告
if (st_AuthConfig.st_XReport.bEnable && !bIsTest)
@@ -501,7 +550,8 @@ int main(int argc, char** argv)
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_WARN, _X("启动服务中,信息报告给API服务器没有启用"));
}
#endif
- XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,功能开关选项,删除功能:%d,登录功能:%d,找回密码:%d,充值功能:%d,注册功能:%d,CDKey功能:%d,公告系统:%d,动态验证:%d,多端登录:%d,临时试用:%d,黑名单功能:%d,普通TOKEN:%d,硬件码登录:%d,硬件码绑定:%d"), st_FunSwitch.bSwitchDelete, st_FunSwitch.bSwitchLogin, st_FunSwitch.bSwitchPass, st_FunSwitch.bSwitchPay, st_FunSwitch.bSwitchRegister, st_FunSwitch.bSwitchCDKey, st_FunSwitch.bSwitchNotice, st_FunSwitch.bSwitchDCode, st_FunSwitch.bSwitchMulti, st_FunSwitch.bSwitchTry, st_FunSwitch.bSwitchBanned, st_FunSwitch.bSwitchTokenLogin, st_FunSwitch.bSwitchHCLogin, st_FunSwitch.bSwitchHWBind);
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,功能开关选项,删除功能:%d,登录功能:%d,找回密码:%d,充值功能:%d,注册功能:%d,CDKey功能:%d,公告系统:%d,动态验证:%d,多端登录:%d,临时试用:%d,黑名单功能:%d,普通TOKEN:%d,硬件码登录:%d,OAuth登录支持:%d,硬件码绑定:%d"), st_FunSwitch.bSwitchDelete, st_FunSwitch.bSwitchLogin, st_FunSwitch.bSwitchPass, st_FunSwitch.bSwitchPay, st_FunSwitch.bSwitchRegister, st_FunSwitch.bSwitchCDKey, st_FunSwitch.bSwitchNotice, st_FunSwitch.bSwitchDCode, st_FunSwitch.bSwitchMulti, st_FunSwitch.bSwitchTry, st_FunSwitch.bSwitchBanned, st_FunSwitch.bSwitchTokenLogin, st_FunSwitch.bSwitchHCLogin, st_FunSwitch.bSwitchOAuth, st_FunSwitch.bSwitchHWBind);
+
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("所有服务成功启动,网络验证服务运行中,XEngien版本:%s%s,发行版本次数:%d,当前运行版本:%s。。。"), BaseLib_Version_XNumberStr(), BaseLib_Version_XTypeStr(), st_AuthConfig.st_XVer.pStl_ListVer->size(), st_AuthConfig.st_XVer.pStl_ListVer->front().c_str());
while (true)
From d7c59baebd29d387ebd2525960b854cd1b89f20d Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Thu, 20 Aug 2026 10:19:46 +0800
Subject: [PATCH 12/15] fixed:delete session token failure when time out
---
.../AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp | 2 +-
.../AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp | 3 ++-
.../XEngine_AuthorizeService/Authorize_Task.cpp | 17 ++++++++---------
3 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp
index b52cb33..ed24011 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp
@@ -177,7 +177,7 @@ bool XEngine_AuthorizeHTTP_Token(LPCXSTR lpszClientAddr, XCHAR** pptszList, int
}
Protocol_Packet_HttpOAuth(tszSDBuffer, &nSDLen, &st_OAuthInfo);
XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP);
- XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,请求关闭TOKEN:%s 成功"), lpszClientAddr, tszTokenStr);
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,请求创建OAuth的TOKEN:%s 成功"), lpszClientAddr, tszTokenStr);
}
return true;
}
\ No newline at end of file
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp
index f0424f0..962302a 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_OAuth.cpp
@@ -78,7 +78,8 @@ bool XEngine_AuthorizeHTTP_OAuth(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, LP
{
DBModule_SQLite_UserQuery(st_OAuthInfo.tszUserName, &st_UserTable);
}
- Session_Token_InsertStr(st_OAuthInfo.tszUserName, &st_UserTable.st_UserInfo, st_OAuthInfo.nExpirationTime);
+ st_UserTable.st_UserInfo.xhToken = 1;
+ Session_Token_InsertStr(st_OAuthInfo.tszTokenStr, &st_UserTable.st_UserInfo, st_OAuthInfo.nExpirationTime);
Protocol_Packet_HttpOAuth2(tszSDBuffer, &nSDLen, &st_OAuthInfo);
XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP);
diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.cpp
index 76c9051..704c3b9 100644
--- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.cpp
+++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.cpp
@@ -64,9 +64,6 @@ void XCALLBACK XEngine_TaskEvent_Client(LPCXSTR lpszUserAddr, LPCXSTR lpszUserNa
void XCALLBACK XEngine_TaskEvent_Token(LPCXSTR lpszTokenStr, int nTimeout, int nTimerenewal, XENGINE_LIBTIME* pSt_LibTime, XENGINE_PROTOCOL_USERINFO* pSt_UserInfo, XPVOID lParam)
{
bool bRemove = true;
- XENGINE_PROTOCOL_USERINFO st_UserInfo;
-
- Session_Token_GetStr(lpszTokenStr, &st_UserInfo);
//自动续期?
if (st_AuthConfig.st_XVerification.st_XToken.bAutoRenewal)
{
@@ -86,13 +83,15 @@ void XCALLBACK XEngine_TaskEvent_Token(LPCXSTR lpszTokenStr, int nTimeout, int n
}
}
- AUTHREG_OAUTHINFO st_OAuthInfo = {};
- _tcsxcpy(st_OAuthInfo.tszTokenStr, lpszTokenStr);
- bool bRet = DBModule_SQLite_OAuthDelete(&st_OAuthInfo);
-
- if (bRemove || bRet)
+ if (1 == pSt_UserInfo->xhToken)
+ {
+ AUTHREG_OAUTHINFO st_OAuthInfo = {};
+ _tcsxcpy(st_OAuthInfo.tszTokenStr, lpszTokenStr);
+ DBModule_SQLite_OAuthDelete(&st_OAuthInfo);
+ }
+ if (bRemove || (1 == pSt_UserInfo->xhToken))
{
Session_Token_DeleteStr(lpszTokenStr);
- XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("Token:%s,用户名:%s,已经超时,权限级别:%d,被移除服务器,移除类型:%s"), lpszTokenStr, st_UserInfo.tszUserName, st_UserInfo.nUserLevel, bRet ? "普通" : "OAuth");
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("Token:%s,用户名:%s,已经超时,权限级别:%d,被移除服务器,移除类型:%s"), lpszTokenStr, pSt_UserInfo->tszUserName, pSt_UserInfo->nUserLevel, 1 == pSt_UserInfo->xhToken ? "OAuth" : "Token");
}
}
\ No newline at end of file
From 93497dca64323f6d744736730f03c580f9cacf63 Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Thu, 20 Aug 2026 10:20:37 +0800
Subject: [PATCH 13/15] update:sql file
---
XEngine_SQL/mysql.sql | 29 +++++++++++++++++++++++------
XEngine_SQL/sqlite.sql | 27 ++++++++++++++++++++++-----
2 files changed, 45 insertions(+), 11 deletions(-)
diff --git a/XEngine_SQL/mysql.sql b/XEngine_SQL/mysql.sql
index d0c6419..194eb21 100644
--- a/XEngine_SQL/mysql.sql
+++ b/XEngine_SQL/mysql.sql
@@ -3,15 +3,15 @@
Source Server : QQCloud
Source Server Type : MySQL
- Source Server Version : 80046 (8.0.46-0ubuntu0.24.04.2)
+ Source Server Version : 80046 (8.0.46-0ubuntu0.24.04.3)
Source Host : 118.25.14.242:3306
Source Schema : authorize
Target Server Type : MySQL
- Target Server Version : 80046 (8.0.46-0ubuntu0.24.04.2)
+ Target Server Version : 80046 (8.0.46-0ubuntu0.24.04.3)
File Encoding : 65001
- Date: 30/06/2026 10:05:45
+ Date: 20/08/2026 10:18:42
*/
SET NAMES utf8mb4;
@@ -80,6 +80,24 @@ CREATE TABLE `Authorize_Login` (
-- Records of Authorize_Login
-- ----------------------------
+-- ----------------------------
+-- Table structure for Authorize_OAuth
+-- ----------------------------
+DROP TABLE IF EXISTS `Authorize_OAuth`;
+CREATE TABLE `Authorize_OAuth` (
+ `tszUserName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+ `tszTokenStr` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL,
+ `tszUPToken` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL,
+ `tszClientID` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+ `tszClientKey` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+ `nExpirationTime` int NOT NULL,
+ `tszCreateTime` datetime NOT NULL
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of Authorize_OAuth
+-- ----------------------------
+
-- ----------------------------
-- Table structure for Authorize_Serial
-- ----------------------------
@@ -127,7 +145,6 @@ CREATE TABLE `Authorize_User` (
`ID` int NOT NULL AUTO_INCREMENT,
`UserName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户名',
`Password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '密码',
- `Token` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Token',
`LeftTime` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '剩余时间',
`EmailAddr` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '电子邮件',
`HardCode` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '设备SN',
@@ -139,11 +156,11 @@ CREATE TABLE `Authorize_User` (
`UPTime` datetime NULL DEFAULT NULL COMMENT '登录时间',
`CreateTime` datetime NOT NULL COMMENT '注册时间',
PRIMARY KEY (`ID`) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC;
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of Authorize_User
-- ----------------------------
-INSERT INTO `Authorize_User` VALUES (1, 'admin', '123123aa', '0', '0', '486179@qq.com', 'DAFD2A2DAD', 1, 13699430000, 511025198881118888, 0, 0, '2022-09-21 15:06:45', '2022-09-21 15:06:45');
+INSERT INTO `Authorize_User` VALUES (1, 'admin', '123123aa', '0', '486179@qq.com', 'DAFD2A2DAD', 1, 13699430000, 511025198881118888, 0, 0, '2022-09-21 15:06:45', '2022-09-21 15:06:45');
SET FOREIGN_KEY_CHECKS = 1;
diff --git a/XEngine_SQL/sqlite.sql b/XEngine_SQL/sqlite.sql
index 7d868a4..47ab23b 100644
--- a/XEngine_SQL/sqlite.sql
+++ b/XEngine_SQL/sqlite.sql
@@ -1,7 +1,7 @@
/*
Navicat Premium Dump SQL
- Source Server : auth
+ Source Server : SQL_User
Source Server Type : SQLite
Source Server Version : 3045000 (3.45.0)
Source Schema : main
@@ -10,7 +10,7 @@
Target Server Version : 3045000 (3.45.0)
File Encoding : 65001
- Date: 30/06/2026 10:05:03
+ Date: 20/08/2026 10:18:57
*/
PRAGMA foreign_keys = false;
@@ -76,6 +76,24 @@ CREATE TABLE "Authorize_Login" (
-- Records of Authorize_Login
-- ----------------------------
+-- ----------------------------
+-- Table structure for Authorize_OAuth
+-- ----------------------------
+DROP TABLE IF EXISTS "Authorize_OAuth";
+CREATE TABLE "Authorize_OAuth" (
+ "tszUserName" TEXT NOT NULL,
+ "tszTokenStr" TEXT,
+ "tszUPToken" TEXT,
+ "tszClientID" text,
+ "tszClientKey" TEXT,
+ "nExpirationTime" integer,
+ "tszCreateTime" DATE NOT NULL
+);
+
+-- ----------------------------
+-- Records of Authorize_OAuth
+-- ----------------------------
+
-- ----------------------------
-- Table structure for Authorize_Serial
-- ----------------------------
@@ -121,7 +139,6 @@ CREATE TABLE "Authorize_User" (
"ID" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"UserName" TEXT NOT NULL,
"Password" TEXT NOT NULL,
- "Token" TEXT NOT NULL,
"LeftTime" TEXT NOT NULL,
"EmailAddr" TEXT NOT NULL,
"HardCode" TEXT,
@@ -137,7 +154,7 @@ CREATE TABLE "Authorize_User" (
-- ----------------------------
-- Records of Authorize_User
-- ----------------------------
-INSERT INTO "Authorize_User" VALUES (1, 'admin', '123123aa', '0', '5', '486179@qq.com', 'DAFD2A2DAD', 1, 13699430000, 511025198881118888, 0, 0, '2022-09-21 15:06:45', '2022-09-21 15:06:45');
+INSERT INTO "Authorize_User" VALUES (1, 'admin', '123123aa', '5', '486179@qq.com', 'DAFD2A2DAD', 1, 13699430000, 511025198881118888, 0, 0, '2022-09-21 15:06:45', '2022-09-21 15:06:45');
-- ----------------------------
-- Table structure for sqlite_sequence
@@ -175,7 +192,7 @@ UPDATE "sqlite_sequence" SET seq = 1 WHERE name = 'Authorize_Serial';
-- ----------------------------
-- Auto increment value for Authorize_TempVer
-- ----------------------------
-UPDATE "sqlite_sequence" SET seq = 41 WHERE name = 'Authorize_TempVer';
+UPDATE "sqlite_sequence" SET seq = 1 WHERE name = 'Authorize_TempVer';
-- ----------------------------
-- Auto increment value for Authorize_User
From 28b91c4a2577cc8501e8d7ec2379bc6be182bd5a Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Thu, 20 Aug 2026 11:28:26 +0800
Subject: [PATCH 14/15] update:read me and document
---
CHANGELOG | 22 ++++++++++++++++++++++
README.en.md | 1 +
README.md | 1 +
XEngine_Docment/Docment_en.docx | Bin 152537 -> 159209 bytes
XEngine_Docment/Docment_zh.docx | Bin 158974 -> 162072 bytes
5 files changed, 24 insertions(+)
diff --git a/CHANGELOG b/CHANGELOG
index c2b92b7..4fcd5ee 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,25 @@
+XEngine_Authorize V3.24.0.1001
+
+增加:创建客户端ID和KEY支持
+增加:oauth 支持插入会话管理器
+增加:撤销,创建和更新auth2.0协议
+更新:依赖库
+修改:http 的token验证不需要需要传递设备类型
+修复:mqtt连接失败没有响应的问题
+修复:创建顺序问题
+修复:ql扫描问题
+删除:客户端用户表的token
+
+added:create client id and key support for token
+added:insert session management for oauth token
+added:revoke create fresh for auth 2.0
+update:depend library
+modify:does not need device type for token with http
+fixed:does not reply when mqtt connect failure
+fixed:generator order incorrect
+fixed:ql scan problem
+delete:client user token
+================================================================
XEngine_Authorize V3.23.0.1001
ci:add agentic workflows for issue triage and auto fix
diff --git a/README.en.md b/README.en.md
index a7dd4ea..2b71852 100644
--- a/README.en.md
+++ b/README.en.md
@@ -50,6 +50,7 @@ feature list:
18. support dynamic verifaction code
19. support mulit login and merge time
20. user bind hardware code
+21. OAuth2.0 Verification Support
## install
diff --git a/README.md b/README.md
index 67d5dbf..8a73f18 100644
--- a/README.md
+++ b/README.md
@@ -50,6 +50,7 @@ c c++network Authorize service
18. 支持动态验证码登录
19. 支持多端登录和合并用时
20. 用户绑定硬件码登录
+21. OAuth2.0 验证支持
## 架构预览
XEngine_Authorize
diff --git a/XEngine_Docment/Docment_en.docx b/XEngine_Docment/Docment_en.docx
index 9a988725ba74f68eceb023667bb528677daf6326..3e5c7b1893b37885fd720544bf874543ea96c54d 100644
GIT binary patch
delta 136153
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