mirror of
https://github.com/kunkundi/crossdesk-server.git
synced 2026-03-22 07:45:07 +08:00
[feat] use sqllite3 to manager device id and password
This commit is contained in:
@@ -1,9 +0,0 @@
|
||||
#include "client_id_generator.h"
|
||||
|
||||
ClientIdGenerator::ClientIdGenerator() {}
|
||||
|
||||
ClientIdGenerator::~ClientIdGenerator() {}
|
||||
|
||||
std::string ClientIdGenerator::GeneratorNewId() {
|
||||
return std::to_string(++base_id_);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2024-08-06
|
||||
* Copyright (c) 2024 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CLIENT_ID_GENERATOR_H_
|
||||
#define _CLIENT_ID_GENERATOR_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
class ClientIdGenerator {
|
||||
public:
|
||||
ClientIdGenerator();
|
||||
~ClientIdGenerator();
|
||||
|
||||
public:
|
||||
std::string GeneratorNewId();
|
||||
|
||||
private:
|
||||
int base_id_ = 300000000;
|
||||
};
|
||||
|
||||
#endif
|
||||
137
src/device_db_manager/device_db_manager.cpp
Normal file
137
src/device_db_manager/device_db_manager.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
#include "device_db_manager.h"
|
||||
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
DeviceDBManager::DeviceDBManager(const std::string& dbPath) : db(nullptr) {
|
||||
if (sqlite3_open(dbPath.c_str(), &db) != SQLITE_OK) {
|
||||
LOG_ERROR("Failed to open database: {} with error msg {}", dbPath,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
initDB();
|
||||
}
|
||||
|
||||
DeviceDBManager::~DeviceDBManager() {
|
||||
if (db) sqlite3_close(db);
|
||||
}
|
||||
|
||||
void DeviceDBManager::initDB() {
|
||||
const char* sql =
|
||||
"CREATE TABLE IF NOT EXISTS devices ("
|
||||
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
|
||||
"device_id TEXT UNIQUE NOT NULL,"
|
||||
"password_hash TEXT NOT NULL);";
|
||||
|
||||
char* errMsg = nullptr;
|
||||
int rc = sqlite3_exec(db, sql, nullptr, nullptr, &errMsg);
|
||||
if (rc != SQLITE_OK) {
|
||||
LOG_ERROR("Failed to initialize DB: {}", errMsg);
|
||||
sqlite3_free(errMsg);
|
||||
}
|
||||
}
|
||||
|
||||
std::string DeviceDBManager::sha256(const std::string& str) {
|
||||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||
SHA256(reinterpret_cast<const unsigned char*>(str.c_str()), str.size(), hash);
|
||||
|
||||
std::stringstream ss;
|
||||
for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i)
|
||||
ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string DeviceDBManager::generateDeviceId() {
|
||||
static std::mt19937 rng(static_cast<unsigned>(
|
||||
std::chrono::steady_clock::now().time_since_epoch().count()));
|
||||
std::uniform_int_distribution<int> dist(0, 9);
|
||||
|
||||
std::string id;
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
id += '0' + dist(rng);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
std::string DeviceDBManager::addDevice(const std::string& password) {
|
||||
std::string hash = sha256(password);
|
||||
|
||||
const int maxTry = 10;
|
||||
for (int i = 0; i < maxTry; ++i) {
|
||||
std::string deviceId = generateDeviceId();
|
||||
|
||||
const char* sql =
|
||||
"INSERT INTO devices (device_id, password_hash) VALUES (?, ?);";
|
||||
sqlite3_stmt* stmt = nullptr;
|
||||
if (sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) != SQLITE_OK) {
|
||||
LOG_ERROR("Failed to prepare insert statement");
|
||||
return "";
|
||||
}
|
||||
|
||||
sqlite3_bind_text(stmt, 1, deviceId.c_str(), -1, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_text(stmt, 2, hash.c_str(), -1, SQLITE_TRANSIENT);
|
||||
|
||||
int rc = sqlite3_step(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
if (rc == SQLITE_DONE) {
|
||||
return deviceId;
|
||||
} else if (rc == SQLITE_CONSTRAINT) {
|
||||
continue;
|
||||
} else {
|
||||
LOG_ERROR("Failed to insert device: {}", sqlite3_errmsg(db));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERROR("Failed to generate unique device ID after {} attempts.", maxTry);
|
||||
return "";
|
||||
}
|
||||
|
||||
bool DeviceDBManager::verifyDevice(const std::string& deviceId,
|
||||
const std::string& password) {
|
||||
std::string hash = sha256(password);
|
||||
const char* sql =
|
||||
"SELECT COUNT(*) FROM devices WHERE device_id = ? AND password_hash = ?;";
|
||||
|
||||
sqlite3_stmt* stmt = nullptr;
|
||||
if (sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) != SQLITE_OK) {
|
||||
LOG_ERROR("Failed to prepare verify statement.");
|
||||
return false;
|
||||
}
|
||||
|
||||
sqlite3_bind_text(stmt, 1, deviceId.c_str(), -1, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_text(stmt, 2, hash.c_str(), -1, SQLITE_TRANSIENT);
|
||||
|
||||
bool found = false;
|
||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
int count = sqlite3_column_int(stmt, 0);
|
||||
found = (count > 0);
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
return found;
|
||||
}
|
||||
|
||||
bool DeviceDBManager::removeDevice(const std::string& deviceId) {
|
||||
const char* sql = "DELETE FROM devices WHERE device_id = ?;";
|
||||
|
||||
sqlite3_stmt* stmt = nullptr;
|
||||
if (sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) != SQLITE_OK) {
|
||||
LOG_ERROR("Failed to prepare delete statement.");
|
||||
return false;
|
||||
}
|
||||
|
||||
sqlite3_bind_text(stmt, 1, deviceId.c_str(), -1, SQLITE_TRANSIENT);
|
||||
|
||||
bool success = (sqlite3_step(stmt) == SQLITE_DONE);
|
||||
sqlite3_finalize(stmt);
|
||||
return success;
|
||||
}
|
||||
37
src/device_db_manager/device_db_manager.h
Normal file
37
src/device_db_manager/device_db_manager.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* @Author: DI JUNKUN
|
||||
* @Date: 2025-06-19
|
||||
* Copyright (c) 2025 by DI JUNKUN, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DEVICE_DB_MANAGER_H_
|
||||
#define _DEVICE_DB_MANAGER_H_
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
class DeviceDBManager {
|
||||
public:
|
||||
explicit DeviceDBManager(const std::string& dbPath);
|
||||
~DeviceDBManager();
|
||||
|
||||
DeviceDBManager(const DeviceDBManager&) = delete;
|
||||
DeviceDBManager& operator=(const DeviceDBManager&) = delete;
|
||||
|
||||
public:
|
||||
std::string addDevice(const std::string& password);
|
||||
|
||||
bool verifyDevice(const std::string& deviceId, const std::string& password);
|
||||
bool removeDevice(const std::string& deviceId);
|
||||
|
||||
private:
|
||||
std::string sha256(const std::string& str);
|
||||
void initDB();
|
||||
std::string generateDeviceId();
|
||||
|
||||
private:
|
||||
sqlite3* db;
|
||||
};
|
||||
|
||||
#endif // _DEVICE_DB_MANAGER_H_
|
||||
@@ -47,6 +47,8 @@ SignalServer::~SignalServer() {}
|
||||
|
||||
bool SignalServer::on_open(websocketpp::connection_hdl hdl) {
|
||||
ws_connections_[hdl] = ws_connection_id_++;
|
||||
|
||||
device_db_manager_ = std::make_unique<DeviceDBManager>("");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -155,7 +157,7 @@ void SignalServer::on_message(websocketpp::connection_hdl hdl,
|
||||
case "login"_H: {
|
||||
std::string host_id = j["user_id"].get<std::string>();
|
||||
if (host_id.empty()) {
|
||||
host_id = client_id_generator_.GeneratorNewId();
|
||||
host_id = ""; // todo
|
||||
LOG_INFO("New client, assign id [{}] to it", host_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <websocketpp/config/asio_no_tls.hpp>
|
||||
#include <websocketpp/server.hpp>
|
||||
|
||||
#include "client_id_generator.h"
|
||||
#include "device_db_manager.h"
|
||||
#include "transmission_manager.h"
|
||||
|
||||
using nlohmann::json;
|
||||
@@ -48,7 +48,7 @@ class SignalServer {
|
||||
|
||||
private:
|
||||
TransmissionManager transmission_manager_;
|
||||
ClientIdGenerator client_id_generator_;
|
||||
std::unique_ptr<DeviceDBManager> device_db_manager_;
|
||||
};
|
||||
|
||||
#endif
|
||||
12
xmake.lua
12
xmake.lua
@@ -6,7 +6,7 @@ set_languages("c++17")
|
||||
|
||||
add_rules("mode.release", "mode.debug")
|
||||
|
||||
add_requires("asio 1.24.0", "nlohmann_json", "spdlog 1.11.0")
|
||||
add_requires("asio 1.24.0", "nlohmann_json", "spdlog 1.14.1", "sqlite3 3.49.0", "openssl")
|
||||
|
||||
add_defines("ASIO_STANDALONE", "ASIO_HAS_STD_TYPE_TRAITS",
|
||||
"ASIO_HAS_STD_SHARED_PTR", "ASIO_HAS_STD_ADDRESSOF", "ASIO_HAS_STD_ATOMIC",
|
||||
@@ -22,7 +22,7 @@ elseif is_os("linux") then
|
||||
set_config("cxxflags", "-fPIC")
|
||||
end
|
||||
|
||||
add_packages("spdlog")
|
||||
add_packages("spdlog", "openssl", "sqlite3")
|
||||
|
||||
includes("thirdparty")
|
||||
|
||||
@@ -36,9 +36,15 @@ target("common")
|
||||
set_kind("headeronly")
|
||||
add_includedirs("src/common", {public = true})
|
||||
|
||||
target("device_db_manager")
|
||||
set_kind("object")
|
||||
add_deps("log")
|
||||
add_files("src/device_db_manager/*.cpp")
|
||||
add_includedirs("src/device_db_manager", {public = true})
|
||||
|
||||
target("signal_server")
|
||||
set_kind("binary")
|
||||
add_deps("log", "common")
|
||||
add_deps("log", "common", "device_db_manager")
|
||||
add_files("src/*.cpp")
|
||||
add_packages("asio", "nlohmann_json", "spdlog")
|
||||
add_includedirs("thirdparty/websocketpp/include")
|
||||
|
||||
Reference in New Issue
Block a user