1023 lines
30 KiB
C++
1023 lines
30 KiB
C++
#include "Login_global.h"
|
||
#include <string>
|
||
#include <memory>
|
||
#include <chrono>
|
||
#include <filesystem>
|
||
#include <sqlite3.h>
|
||
#include <openssl/evp.h>
|
||
#include <openssl/sha.h>
|
||
#include <nlohmann/json.hpp>
|
||
#include <cstring>
|
||
#include <stdexcept>
|
||
#include <sstream>
|
||
#include <iomanip>
|
||
#include <iostream>
|
||
#include <vector>
|
||
#include <algorithm>
|
||
#include <openssl/rand.h>
|
||
#include <openssl/bio.h>
|
||
#include <openssl/buffer.h>
|
||
|
||
using json = nlohmann::json;
|
||
namespace fs = std::filesystem;
|
||
|
||
std::string generateSalt(const std::string &username)
|
||
{
|
||
// 使用用户名生成盐值
|
||
return username + "XNSim_Salt_Key";
|
||
}
|
||
|
||
std::string encryptPassword(const std::string &password, const std::string &salt)
|
||
{
|
||
// 将密码和盐值组合
|
||
std::string saltedPassword = password;
|
||
if (!salt.empty()) {
|
||
saltedPassword += salt;
|
||
}
|
||
|
||
// 使用SHA-256算法对加盐密码进行加密
|
||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||
EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
|
||
EVP_DigestUpdate(ctx, saltedPassword.c_str(), saltedPassword.length());
|
||
EVP_DigestFinal_ex(ctx, hash, NULL);
|
||
EVP_MD_CTX_free(ctx);
|
||
|
||
// 转换为十六进制字符串
|
||
std::stringstream ss;
|
||
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
|
||
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(hash[i]);
|
||
}
|
||
return ss.str();
|
||
}
|
||
|
||
// Base64编码函数
|
||
std::string base64_encode(const unsigned char *data, size_t length)
|
||
{
|
||
BIO *bio, *b64;
|
||
BUF_MEM *bufferPtr;
|
||
|
||
b64 = BIO_new(BIO_f_base64());
|
||
bio = BIO_new(BIO_s_mem());
|
||
bio = BIO_push(b64, bio);
|
||
|
||
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); // 不添加换行符
|
||
BIO_write(bio, data, length);
|
||
BIO_flush(bio);
|
||
BIO_get_mem_ptr(bio, &bufferPtr);
|
||
|
||
std::string result(bufferPtr->data, bufferPtr->length);
|
||
BIO_free_all(bio);
|
||
|
||
return result;
|
||
}
|
||
|
||
// Base64解码函数
|
||
std::vector<unsigned char> base64_decode(const std::string &encoded_string)
|
||
{
|
||
BIO *bio, *b64;
|
||
std::vector<unsigned char> result;
|
||
|
||
b64 = BIO_new(BIO_f_base64());
|
||
bio = BIO_new_mem_buf(encoded_string.c_str(), encoded_string.length());
|
||
bio = BIO_push(b64, bio);
|
||
|
||
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); // 不添加换行符
|
||
|
||
// 计算解码后的长度
|
||
size_t decoded_length = (encoded_string.length() * 3) / 4;
|
||
result.resize(decoded_length);
|
||
|
||
int actual_length = BIO_read(bio, result.data(), decoded_length);
|
||
if (actual_length > 0) {
|
||
result.resize(actual_length);
|
||
} else {
|
||
result.clear();
|
||
}
|
||
|
||
BIO_free_all(bio);
|
||
return result;
|
||
}
|
||
|
||
// 利用用户名和固定密钥派生32字节AES密钥
|
||
std::vector<unsigned char> derive_aes_key(const std::string &username, const std::string &fixed_key)
|
||
{
|
||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||
std::string key_material = username + fixed_key;
|
||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||
EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
|
||
EVP_DigestUpdate(ctx, key_material.c_str(), key_material.length());
|
||
EVP_DigestFinal_ex(ctx, hash, NULL);
|
||
EVP_MD_CTX_free(ctx);
|
||
return std::vector<unsigned char>(hash, hash + SHA256_DIGEST_LENGTH);
|
||
}
|
||
|
||
// AES-256-CBC加密
|
||
std::vector<unsigned char> aes_encrypt(const std::string &plaintext,
|
||
const std::vector<unsigned char> &key,
|
||
std::vector<unsigned char> &iv_out)
|
||
{
|
||
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
|
||
if (!ctx)
|
||
throw std::runtime_error("EVP_CIPHER_CTX_new failed");
|
||
iv_out.resize(16);
|
||
if (!RAND_bytes(iv_out.data(), iv_out.size())) {
|
||
EVP_CIPHER_CTX_free(ctx);
|
||
throw std::runtime_error("RAND_bytes failed");
|
||
}
|
||
if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key.data(), iv_out.data()))
|
||
throw std::runtime_error("EVP_EncryptInit_ex failed");
|
||
std::vector<unsigned char> ciphertext(plaintext.size() + 16);
|
||
int len = 0, ciphertext_len = 0;
|
||
if (1
|
||
!= EVP_EncryptUpdate(ctx, ciphertext.data(), &len,
|
||
reinterpret_cast<const unsigned char *>(plaintext.c_str()),
|
||
plaintext.size()))
|
||
throw std::runtime_error("EVP_EncryptUpdate failed");
|
||
ciphertext_len = len;
|
||
if (1 != EVP_EncryptFinal_ex(ctx, ciphertext.data() + len, &len))
|
||
throw std::runtime_error("EVP_EncryptFinal_ex failed");
|
||
ciphertext_len += len;
|
||
ciphertext.resize(ciphertext_len);
|
||
EVP_CIPHER_CTX_free(ctx);
|
||
return ciphertext;
|
||
}
|
||
|
||
// AES-256-CBC解密
|
||
std::string aes_decrypt(const std::vector<unsigned char> &ciphertext,
|
||
const std::vector<unsigned char> &key, const std::vector<unsigned char> &iv)
|
||
{
|
||
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
|
||
if (!ctx)
|
||
throw std::runtime_error("EVP_CIPHER_CTX_new failed");
|
||
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key.data(), iv.data()))
|
||
throw std::runtime_error("EVP_DecryptInit_ex failed");
|
||
std::vector<unsigned char> plaintext(ciphertext.size());
|
||
int len = 0, plaintext_len = 0;
|
||
if (1 != EVP_DecryptUpdate(ctx, plaintext.data(), &len, ciphertext.data(), ciphertext.size()))
|
||
throw std::runtime_error("EVP_DecryptUpdate failed");
|
||
plaintext_len = len;
|
||
if (1 != EVP_DecryptFinal_ex(ctx, plaintext.data() + len, &len))
|
||
throw std::runtime_error("EVP_DecryptFinal_ex failed");
|
||
plaintext_len += len;
|
||
plaintext.resize(plaintext_len);
|
||
EVP_CIPHER_CTX_free(ctx);
|
||
return std::string(plaintext.begin(), plaintext.end());
|
||
}
|
||
|
||
// 二进制转16进制字符串
|
||
std::string bin2hex(const std::vector<unsigned char> &data)
|
||
{
|
||
std::ostringstream oss;
|
||
for (auto c : data) {
|
||
oss << std::hex << std::setw(2) << std::setfill('0') << (int)c;
|
||
}
|
||
return oss.str();
|
||
}
|
||
|
||
// 16进制字符串转二进制
|
||
std::vector<unsigned char> hex2bin(const std::string &hex)
|
||
{
|
||
std::vector<unsigned char> out;
|
||
for (size_t i = 0; i + 1 < hex.length(); i += 2) {
|
||
std::string byteString = hex.substr(i, 2);
|
||
unsigned char byte = (unsigned char)strtol(byteString.c_str(), nullptr, 16);
|
||
out.push_back(byte);
|
||
}
|
||
return out;
|
||
}
|
||
|
||
extern "C" LOGIN_EXPORT int validateUser(const char *username_buffer, size_t username_length,
|
||
const char *password_buffer, size_t password_length)
|
||
{
|
||
try {
|
||
std::string username_str(username_buffer, username_length);
|
||
std::string password_str(password_buffer, password_length);
|
||
|
||
if (username_str.empty() || password_str.empty()) {
|
||
return -1;
|
||
}
|
||
|
||
std::string salt = generateSalt(username_str);
|
||
std::string encryptedPassword = encryptPassword(password_str, salt);
|
||
|
||
// 获取环境变量
|
||
const char *xnCorePath = std::getenv("XNCore");
|
||
if (!xnCorePath) {
|
||
return -1;
|
||
}
|
||
|
||
fs::path dbPath = fs::path(xnCorePath) / "database" / "UserInfo.db";
|
||
|
||
sqlite3 *db;
|
||
if (sqlite3_open(dbPath.string().c_str(), &db) != SQLITE_OK) {
|
||
return -1;
|
||
}
|
||
|
||
int userId = -1;
|
||
sqlite3_stmt *stmt;
|
||
const char *queryStr = "SELECT * FROM users WHERE username = ? AND password = ?";
|
||
|
||
if (sqlite3_prepare_v2(db, queryStr, -1, &stmt, nullptr) == SQLITE_OK) {
|
||
sqlite3_bind_text(stmt, 1, username_str.c_str(), -1, SQLITE_STATIC);
|
||
sqlite3_bind_text(stmt, 2, encryptedPassword.c_str(), -1, SQLITE_STATIC);
|
||
|
||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||
userId = sqlite3_column_int(stmt, 0);
|
||
}
|
||
|
||
sqlite3_finalize(stmt);
|
||
}
|
||
|
||
sqlite3_close(db);
|
||
return userId;
|
||
|
||
} catch (const std::exception &) {
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
extern "C" LOGIN_EXPORT int getUserInfo(int user_id, char *result, int result_length)
|
||
{
|
||
try {
|
||
const char *xnCorePath = std::getenv("XNCore");
|
||
if (!xnCorePath) {
|
||
std::cout << "xnCorePath is null" << std::endl;
|
||
return -1;
|
||
}
|
||
|
||
fs::path dbPath = fs::path(xnCorePath) / "database" / "UserInfo.db";
|
||
|
||
sqlite3 *db;
|
||
if (sqlite3_open(dbPath.string().c_str(), &db) != SQLITE_OK) {
|
||
std::cout << "sqlite3_open failed" << std::endl;
|
||
return -1;
|
||
}
|
||
|
||
sqlite3_stmt *stmt;
|
||
const char *queryStr = "SELECT * FROM users WHERE id = ?";
|
||
|
||
if (sqlite3_prepare_v2(db, queryStr, -1, &stmt, nullptr) == SQLITE_OK) {
|
||
sqlite3_bind_int(stmt, 1, user_id);
|
||
|
||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||
json userInfo;
|
||
userInfo["id"] = sqlite3_column_int(stmt, 0);
|
||
userInfo["username"] = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1));
|
||
// access_level 解密
|
||
std::string accessLevelEnc =
|
||
reinterpret_cast<const char *>(sqlite3_column_text(stmt, 3));
|
||
std::vector<unsigned char> iv_and_ciphertext = hex2bin(accessLevelEnc);
|
||
if (iv_and_ciphertext.size() < 16) {
|
||
userInfo["access_level"] = nullptr;
|
||
} else {
|
||
std::vector<unsigned char> iv(iv_and_ciphertext.begin(),
|
||
iv_and_ciphertext.begin() + 16);
|
||
std::vector<unsigned char> ciphertext(iv_and_ciphertext.begin() + 16,
|
||
iv_and_ciphertext.end());
|
||
std::string fixed_key = "XNSim_Access_Key";
|
||
std::string username = userInfo["username"].get<std::string>();
|
||
std::vector<unsigned char> key = derive_aes_key(username, fixed_key);
|
||
try {
|
||
std::string accessLevelStr = aes_decrypt(ciphertext, key, iv);
|
||
userInfo["access_level"] = std::stoi(accessLevelStr);
|
||
} catch (...) {
|
||
userInfo["access_level"] = nullptr;
|
||
}
|
||
}
|
||
userInfo["full_name"] =
|
||
reinterpret_cast<const char *>(sqlite3_column_text(stmt, 4));
|
||
userInfo["phone"] = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 5));
|
||
userInfo["email"] = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 6));
|
||
userInfo["department"] =
|
||
reinterpret_cast<const char *>(sqlite3_column_text(stmt, 7));
|
||
userInfo["position"] = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 8));
|
||
|
||
// 处理二进制数据
|
||
const void *blob_data = sqlite3_column_blob(stmt, 9);
|
||
int blob_size = sqlite3_column_bytes(stmt, 9);
|
||
if (blob_data && blob_size > 0) {
|
||
userInfo["icon"] =
|
||
base64_encode(static_cast<const unsigned char *>(blob_data), blob_size);
|
||
} else {
|
||
userInfo["icon"] = nullptr; // 使用null值代替空字符串
|
||
}
|
||
|
||
std::string jsonData = userInfo.dump();
|
||
if (result_length >= jsonData.size() + 1) {
|
||
std::strcpy(result, jsonData.c_str());
|
||
sqlite3_finalize(stmt);
|
||
sqlite3_close(db);
|
||
return 0;
|
||
} else {
|
||
std::cout << "result_length: " << result_length << std::endl;
|
||
sqlite3_finalize(stmt);
|
||
sqlite3_close(db);
|
||
return -1;
|
||
}
|
||
} else {
|
||
// 用户不存在
|
||
sqlite3_finalize(stmt);
|
||
sqlite3_close(db);
|
||
return -2; // 用户不存在
|
||
}
|
||
}
|
||
|
||
sqlite3_close(db);
|
||
return 0;
|
||
|
||
} catch (const std::exception &) {
|
||
std::cout << "getUserInfo failed" << std::endl;
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
extern "C" LOGIN_EXPORT void freeUserInfo(const char *ptr)
|
||
{
|
||
if (ptr) {
|
||
delete[] ptr;
|
||
}
|
||
}
|
||
|
||
extern "C" LOGIN_EXPORT void cleanup()
|
||
{
|
||
}
|
||
|
||
// 检查用户名是否已存在
|
||
int checkUsernameExists(const void *username_buffer, size_t username_length)
|
||
{
|
||
try {
|
||
const char *username_data = static_cast<const char *>(username_buffer);
|
||
std::string username_str(username_data, username_length);
|
||
|
||
if (username_str.empty()) {
|
||
return -1;
|
||
}
|
||
|
||
const char *xnCorePath = std::getenv("XNCore");
|
||
if (!xnCorePath) {
|
||
return -1;
|
||
}
|
||
|
||
fs::path dbPath = fs::path(xnCorePath) / "database" / "UserInfo.db";
|
||
std::string connectionName =
|
||
"usercheck_"
|
||
+ std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(
|
||
std::chrono::system_clock::now().time_since_epoch())
|
||
.count());
|
||
|
||
int result = -1;
|
||
{
|
||
sqlite3 *db;
|
||
if (sqlite3_open(dbPath.string().c_str(), &db) != SQLITE_OK) {
|
||
return -1;
|
||
}
|
||
|
||
sqlite3_stmt *stmt;
|
||
const char *queryStr = "SELECT COUNT(*) FROM users WHERE username = ?";
|
||
|
||
if (sqlite3_prepare_v2(db, queryStr, -1, &stmt, nullptr) == SQLITE_OK) {
|
||
sqlite3_bind_text(stmt, 1, username_str.c_str(), -1, SQLITE_STATIC);
|
||
|
||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||
result = sqlite3_column_int(stmt, 0) > 0 ? 1 : 0;
|
||
}
|
||
|
||
sqlite3_finalize(stmt);
|
||
}
|
||
|
||
sqlite3_close(db);
|
||
}
|
||
return result;
|
||
|
||
} catch (const std::exception &) {
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
// 注册新用户
|
||
extern "C" LOGIN_EXPORT int registerUser(const char *username_buffer, int username_length,
|
||
const char *password_buffer, int password_length,
|
||
const char *userinfo_buffer, int userinfo_length)
|
||
{
|
||
try {
|
||
// 转换输入参数
|
||
std::string username_str(username_buffer, username_length);
|
||
std::string password_str(password_buffer, password_length);
|
||
std::string userinfo_str(userinfo_buffer, userinfo_length);
|
||
|
||
// 验证用户名和密码非空
|
||
if (username_str.empty()) {
|
||
return -4; // 用户名为空
|
||
}
|
||
if (password_str.empty()) {
|
||
return -5; // 密码为空
|
||
}
|
||
|
||
// 检查用户名是否已存在
|
||
if (checkUsernameExists(username_buffer, username_length) != 0) {
|
||
return -2; // 用户名已存在
|
||
}
|
||
|
||
// 解析用户信息JSON
|
||
json userInfo;
|
||
try {
|
||
userInfo = json::parse(userinfo_str);
|
||
} catch (const json::parse_error &) {
|
||
return -3; // Invalid user info format
|
||
}
|
||
|
||
// 验证权限级别
|
||
int accessLevel = 0;
|
||
if (userInfo.contains("access_level")) {
|
||
accessLevel = userInfo["access_level"].get<int>();
|
||
}
|
||
// access_level 加密
|
||
std::string fixed_key = "XNSim_Access_Key";
|
||
std::vector<unsigned char> key = derive_aes_key(username_str, fixed_key);
|
||
std::vector<unsigned char> iv;
|
||
std::vector<unsigned char> ciphertext = aes_encrypt(std::to_string(accessLevel), key, iv);
|
||
std::vector<unsigned char> iv_and_ciphertext = iv;
|
||
iv_and_ciphertext.insert(iv_and_ciphertext.end(), ciphertext.begin(), ciphertext.end());
|
||
std::string accessLevelEnc = bin2hex(iv_and_ciphertext);
|
||
|
||
// 生成加密密码
|
||
std::string salt = generateSalt(username_str);
|
||
std::string encryptedPassword = encryptPassword(password_str, salt);
|
||
|
||
// 连接数据库
|
||
const char *xnCorePath = std::getenv("XNCore");
|
||
if (!xnCorePath) {
|
||
return -1;
|
||
}
|
||
|
||
fs::path dbPath = fs::path(xnCorePath) / "database" / "UserInfo.db";
|
||
|
||
int newUserId = -1;
|
||
{
|
||
sqlite3 *db;
|
||
if (sqlite3_open(dbPath.string().c_str(), &db) != SQLITE_OK) {
|
||
return -1;
|
||
}
|
||
|
||
sqlite3_stmt *stmt;
|
||
const char *queryStr =
|
||
"INSERT INTO users (username, password, access_level, full_name, phone, "
|
||
"email, department, position) "
|
||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
||
|
||
if (sqlite3_prepare_v2(db, queryStr, -1, &stmt, nullptr) == SQLITE_OK) {
|
||
sqlite3_bind_text(stmt, 1, username_str.c_str(), -1, SQLITE_STATIC);
|
||
sqlite3_bind_text(stmt, 2, encryptedPassword.c_str(), -1, SQLITE_STATIC);
|
||
sqlite3_bind_text(stmt, 3, accessLevelEnc.c_str(), -1, SQLITE_STATIC);
|
||
sqlite3_bind_text(stmt, 4, userInfo["full_name"].get<std::string>().c_str(), -1,
|
||
SQLITE_STATIC);
|
||
sqlite3_bind_text(stmt, 5, userInfo["phone"].get<std::string>().c_str(), -1,
|
||
SQLITE_STATIC);
|
||
sqlite3_bind_text(stmt, 6, userInfo["email"].get<std::string>().c_str(), -1,
|
||
SQLITE_STATIC);
|
||
sqlite3_bind_text(stmt, 7, userInfo["department"].get<std::string>().c_str(), -1,
|
||
SQLITE_STATIC);
|
||
sqlite3_bind_text(stmt, 8, userInfo["position"].get<std::string>().c_str(), -1,
|
||
SQLITE_STATIC);
|
||
|
||
if (sqlite3_step(stmt) == SQLITE_DONE) {
|
||
newUserId = sqlite3_last_insert_rowid(db);
|
||
}
|
||
|
||
sqlite3_finalize(stmt);
|
||
}
|
||
|
||
sqlite3_close(db);
|
||
}
|
||
return newUserId;
|
||
|
||
} catch (const std::exception &) {
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
// 修改密码
|
||
extern "C" LOGIN_EXPORT int changePassword(int user_id, const char *old_password_buffer,
|
||
int old_password_length, const char *new_password_buffer,
|
||
int new_password_length)
|
||
{
|
||
try {
|
||
std::string old_password_str(old_password_buffer, old_password_length);
|
||
std::string new_password_str(new_password_buffer, new_password_length);
|
||
|
||
if (old_password_str.empty() || new_password_str.empty()) {
|
||
return -1;
|
||
}
|
||
|
||
if (old_password_str == new_password_str) {
|
||
return -2;
|
||
}
|
||
|
||
const char *xnCorePath = std::getenv("XNCore");
|
||
if (!xnCorePath) {
|
||
return -3;
|
||
}
|
||
|
||
fs::path dbPath = fs::path(xnCorePath) / "database" / "UserInfo.db";
|
||
|
||
{
|
||
sqlite3 *db;
|
||
if (sqlite3_open(dbPath.string().c_str(), &db) != SQLITE_OK) {
|
||
return -3;
|
||
}
|
||
|
||
// 首先验证旧密码
|
||
sqlite3_stmt *stmt;
|
||
const char *queryStr = "SELECT username, password FROM users WHERE id = ?";
|
||
|
||
if (sqlite3_prepare_v2(db, queryStr, -1, &stmt, nullptr) == SQLITE_OK) {
|
||
sqlite3_bind_int(stmt, 1, user_id);
|
||
|
||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||
std::string username =
|
||
reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0));
|
||
std::string storedPassword =
|
||
reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1));
|
||
|
||
// 验证旧密码
|
||
std::string salt = generateSalt(username);
|
||
std::string encryptedOldPassword = encryptPassword(old_password_str, salt);
|
||
|
||
if (encryptedOldPassword != storedPassword) {
|
||
sqlite3_finalize(stmt);
|
||
sqlite3_close(db);
|
||
return -4; // 旧密码错误
|
||
}
|
||
|
||
// 生成新的加密密码
|
||
std::string encryptedNewPassword = encryptPassword(new_password_str, salt);
|
||
|
||
// 更新密码
|
||
sqlite3_finalize(stmt);
|
||
stmt = nullptr;
|
||
queryStr = "UPDATE users SET password = ? WHERE id = ?";
|
||
|
||
if (sqlite3_prepare_v2(db, queryStr, -1, &stmt, nullptr) == SQLITE_OK) {
|
||
sqlite3_bind_text(stmt, 1, encryptedNewPassword.c_str(), -1, SQLITE_STATIC);
|
||
sqlite3_bind_int(stmt, 2, user_id);
|
||
|
||
if (sqlite3_step(stmt) == SQLITE_DONE) {
|
||
sqlite3_finalize(stmt);
|
||
sqlite3_close(db);
|
||
return 0; // 密码修改成功
|
||
}
|
||
|
||
sqlite3_finalize(stmt);
|
||
}
|
||
} else {
|
||
// 用户不存在
|
||
sqlite3_finalize(stmt);
|
||
sqlite3_close(db);
|
||
return -5; // 用户不存在
|
||
}
|
||
}
|
||
|
||
sqlite3_close(db);
|
||
}
|
||
|
||
return -6; // Default error return
|
||
} catch (const std::exception &) {
|
||
return -3;
|
||
}
|
||
}
|
||
|
||
extern "C" LOGIN_EXPORT int resetPassword(int user_id)
|
||
{
|
||
try {
|
||
const char *xnCorePath = std::getenv("XNCore");
|
||
if (!xnCorePath) {
|
||
return -1;
|
||
}
|
||
|
||
fs::path dbPath = fs::path(xnCorePath) / "database" / "UserInfo.db";
|
||
{
|
||
sqlite3 *db;
|
||
if (sqlite3_open(dbPath.string().c_str(), &db) != SQLITE_OK) {
|
||
return -2;
|
||
}
|
||
|
||
// 首先查询用户名
|
||
sqlite3_stmt *stmt;
|
||
const char *queryStr = "SELECT username FROM users WHERE id = ?";
|
||
|
||
if (sqlite3_prepare_v2(db, queryStr, -1, &stmt, nullptr) != SQLITE_OK) {
|
||
sqlite3_close(db);
|
||
return -3; // SELECT 语句准备失败
|
||
}
|
||
|
||
sqlite3_bind_int(stmt, 1, user_id);
|
||
|
||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||
std::string username = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0));
|
||
|
||
// 生成新的加密密码
|
||
std::string salt = generateSalt(username);
|
||
std::string new_password_str = "123456";
|
||
std::string encryptedNewPassword = encryptPassword(new_password_str, salt);
|
||
|
||
// 更新密码
|
||
sqlite3_finalize(stmt);
|
||
stmt = nullptr;
|
||
queryStr = "UPDATE users SET password = ? WHERE id = ?";
|
||
|
||
if (sqlite3_prepare_v2(db, queryStr, -1, &stmt, nullptr) != SQLITE_OK) {
|
||
sqlite3_close(db);
|
||
return -4; // UPDATE 语句准备失败
|
||
}
|
||
|
||
sqlite3_bind_text(stmt, 1, encryptedNewPassword.c_str(), -1, SQLITE_STATIC);
|
||
sqlite3_bind_int(stmt, 2, user_id);
|
||
|
||
if (sqlite3_step(stmt) == SQLITE_DONE) {
|
||
sqlite3_finalize(stmt);
|
||
sqlite3_close(db);
|
||
return 0; // 密码重置成功
|
||
} else {
|
||
// 获取具体的错误信息
|
||
int error_code = sqlite3_errcode(db);
|
||
const char *error_msg = sqlite3_errmsg(db);
|
||
std::cout << "UPDATE failed with error code: " << error_code
|
||
<< ", message: " << (error_msg ? error_msg : "unknown") << std::endl;
|
||
sqlite3_finalize(stmt);
|
||
sqlite3_close(db);
|
||
return -5; // UPDATE 语句执行失败
|
||
}
|
||
} else {
|
||
// 用户不存在
|
||
sqlite3_finalize(stmt);
|
||
sqlite3_close(db);
|
||
return -6; // 用户不存在
|
||
}
|
||
}
|
||
|
||
return -7; // 其他错误
|
||
} catch (const std::exception &) {
|
||
return -8;
|
||
}
|
||
}
|
||
|
||
// 更新用户信息
|
||
extern "C" LOGIN_EXPORT int updateUserInfo(int user_id, const char *userinfo_buffer,
|
||
int userinfo_length)
|
||
{
|
||
try {
|
||
std::string userinfo_str(userinfo_buffer, userinfo_length);
|
||
|
||
// 解析用户信息JSON
|
||
json userInfo;
|
||
try {
|
||
userInfo = json::parse(userinfo_str);
|
||
} catch (const json::parse_error &) {
|
||
return -1; // Invalid user info format
|
||
}
|
||
|
||
// 连接数据库
|
||
const char *xnCorePath = std::getenv("XNCore");
|
||
if (!xnCorePath) {
|
||
return -1;
|
||
}
|
||
|
||
fs::path dbPath = fs::path(xnCorePath) / "database" / "UserInfo.db";
|
||
|
||
int result = -1;
|
||
{
|
||
sqlite3 *db;
|
||
if (sqlite3_open(dbPath.string().c_str(), &db) != SQLITE_OK) {
|
||
return -1;
|
||
}
|
||
|
||
// 首先检查用户是否存在
|
||
sqlite3_stmt *stmt;
|
||
const char *checkQueryStr = "SELECT id FROM users WHERE id = ?";
|
||
|
||
if (sqlite3_prepare_v2(db, checkQueryStr, -1, &stmt, nullptr) == SQLITE_OK) {
|
||
sqlite3_bind_int(stmt, 1, user_id);
|
||
|
||
if (sqlite3_step(stmt) != SQLITE_ROW) {
|
||
sqlite3_finalize(stmt);
|
||
sqlite3_close(db);
|
||
return -2; // 用户不存在
|
||
}
|
||
sqlite3_finalize(stmt);
|
||
}
|
||
|
||
stmt = nullptr;
|
||
const char *queryStr =
|
||
"UPDATE users SET full_name = ?, phone = ?, email = ?, department = ?, "
|
||
"position = ? "
|
||
"WHERE id = ?";
|
||
|
||
if (sqlite3_prepare_v2(db, queryStr, -1, &stmt, nullptr) == SQLITE_OK) {
|
||
// 安全地获取字符串值,处理null情况
|
||
std::string full_name =
|
||
userInfo.contains("full_name") && !userInfo["full_name"].is_null()
|
||
? userInfo["full_name"].get<std::string>()
|
||
: "";
|
||
std::string phone = userInfo.contains("phone") && !userInfo["phone"].is_null()
|
||
? userInfo["phone"].get<std::string>()
|
||
: "";
|
||
std::string email = userInfo.contains("email") && !userInfo["email"].is_null()
|
||
? userInfo["email"].get<std::string>()
|
||
: "";
|
||
std::string department =
|
||
userInfo.contains("department") && !userInfo["department"].is_null()
|
||
? userInfo["department"].get<std::string>()
|
||
: "";
|
||
std::string position =
|
||
userInfo.contains("position") && !userInfo["position"].is_null()
|
||
? userInfo["position"].get<std::string>()
|
||
: "";
|
||
|
||
sqlite3_bind_text(stmt, 1, full_name.c_str(), -1, SQLITE_TRANSIENT);
|
||
sqlite3_bind_text(stmt, 2, phone.c_str(), -1, SQLITE_TRANSIENT);
|
||
sqlite3_bind_text(stmt, 3, email.c_str(), -1, SQLITE_TRANSIENT);
|
||
sqlite3_bind_text(stmt, 4, department.c_str(), -1, SQLITE_TRANSIENT);
|
||
sqlite3_bind_text(stmt, 5, position.c_str(), -1, SQLITE_TRANSIENT);
|
||
sqlite3_bind_int(stmt, 6, user_id);
|
||
|
||
if (sqlite3_step(stmt) == SQLITE_DONE) {
|
||
result = 0; // 更新成功
|
||
}
|
||
|
||
sqlite3_finalize(stmt);
|
||
}
|
||
|
||
sqlite3_close(db);
|
||
}
|
||
return result;
|
||
|
||
} catch (const std::exception &) {
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
// 更新用户权限级别
|
||
extern "C" LOGIN_EXPORT int updateUserAccessLevel(int user_id, int access_level)
|
||
{
|
||
try {
|
||
// 验证权限级别
|
||
if (access_level < 0 || access_level > 3) {
|
||
return -3; // 无效的权限级别
|
||
}
|
||
|
||
// 连接数据库
|
||
const char *xnCorePath = std::getenv("XNCore");
|
||
if (!xnCorePath) {
|
||
return -1;
|
||
}
|
||
|
||
fs::path dbPath = fs::path(xnCorePath) / "database" / "UserInfo.db";
|
||
|
||
int result = -1;
|
||
{
|
||
sqlite3 *db;
|
||
if (sqlite3_open(dbPath.string().c_str(), &db) != SQLITE_OK) {
|
||
return -1;
|
||
}
|
||
|
||
// 首先检查用户是否存在
|
||
sqlite3_stmt *stmt;
|
||
const char *checkQueryStr = "SELECT id FROM users WHERE id = ?";
|
||
|
||
if (sqlite3_prepare_v2(db, checkQueryStr, -1, &stmt, nullptr) == SQLITE_OK) {
|
||
sqlite3_bind_int(stmt, 1, user_id);
|
||
|
||
if (sqlite3_step(stmt) != SQLITE_ROW) {
|
||
sqlite3_finalize(stmt);
|
||
sqlite3_close(db);
|
||
return -2; // 用户不存在
|
||
}
|
||
sqlite3_finalize(stmt);
|
||
}
|
||
|
||
stmt = nullptr;
|
||
const char *queryStr = "UPDATE users SET access_level = ? WHERE id = ?";
|
||
|
||
if (sqlite3_prepare_v2(db, queryStr, -1, &stmt, nullptr) == SQLITE_OK) {
|
||
// 需要查用户名
|
||
std::string username;
|
||
{
|
||
sqlite3_stmt *stmt2;
|
||
const char *q2 = "SELECT username FROM users WHERE id = ?";
|
||
if (sqlite3_prepare_v2(db, q2, -1, &stmt2, nullptr) == SQLITE_OK) {
|
||
sqlite3_bind_int(stmt2, 1, user_id);
|
||
if (sqlite3_step(stmt2) == SQLITE_ROW) {
|
||
username =
|
||
reinterpret_cast<const char *>(sqlite3_column_text(stmt2, 0));
|
||
}
|
||
sqlite3_finalize(stmt2);
|
||
}
|
||
}
|
||
std::string fixed_key = "XNSim_Access_Key";
|
||
std::vector<unsigned char> key = derive_aes_key(username, fixed_key);
|
||
std::vector<unsigned char> iv;
|
||
std::vector<unsigned char> ciphertext =
|
||
aes_encrypt(std::to_string(access_level), key, iv);
|
||
std::vector<unsigned char> iv_and_ciphertext = iv;
|
||
iv_and_ciphertext.insert(iv_and_ciphertext.end(), ciphertext.begin(),
|
||
ciphertext.end());
|
||
std::string accessLevelEnc = bin2hex(iv_and_ciphertext);
|
||
sqlite3_bind_text(stmt, 1, accessLevelEnc.c_str(), -1, SQLITE_STATIC);
|
||
sqlite3_bind_int(stmt, 2, user_id);
|
||
|
||
if (sqlite3_step(stmt) == SQLITE_DONE) {
|
||
result = 0; // 更新成功
|
||
}
|
||
|
||
sqlite3_finalize(stmt);
|
||
}
|
||
|
||
sqlite3_close(db);
|
||
}
|
||
return result;
|
||
|
||
} catch (const std::exception &) {
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
// 获取所有用户的username、full_name和access_level,返回JSON数组字符串
|
||
extern "C" LOGIN_EXPORT int getAllUsersSimpleInfo(char *result, int result_length)
|
||
{
|
||
try {
|
||
const char *xnCorePath = std::getenv("XNCore");
|
||
if (!xnCorePath) {
|
||
return -1;
|
||
}
|
||
fs::path dbPath = fs::path(xnCorePath) / "database" / "UserInfo.db";
|
||
sqlite3 *db;
|
||
if (sqlite3_open(dbPath.string().c_str(), &db) != SQLITE_OK) {
|
||
return -1;
|
||
}
|
||
const char *queryStr = "SELECT id, username, full_name, access_level FROM users";
|
||
sqlite3_stmt *stmt;
|
||
json arr = json::array();
|
||
if (sqlite3_prepare_v2(db, queryStr, -1, &stmt, nullptr) == SQLITE_OK) {
|
||
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
||
json userInfo;
|
||
userInfo["id"] = sqlite3_column_int(stmt, 0);
|
||
std::string username = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1));
|
||
userInfo["username"] = username;
|
||
userInfo["full_name"] =
|
||
reinterpret_cast<const char *>(sqlite3_column_text(stmt, 2));
|
||
// access_level 解密
|
||
std::string accessLevelEnc =
|
||
reinterpret_cast<const char *>(sqlite3_column_text(stmt, 3));
|
||
std::vector<unsigned char> iv_and_ciphertext = hex2bin(accessLevelEnc);
|
||
if (iv_and_ciphertext.size() < 16) {
|
||
userInfo["access_level"] = nullptr;
|
||
} else {
|
||
std::vector<unsigned char> iv(iv_and_ciphertext.begin(),
|
||
iv_and_ciphertext.begin() + 16);
|
||
std::vector<unsigned char> ciphertext(iv_and_ciphertext.begin() + 16,
|
||
iv_and_ciphertext.end());
|
||
std::string fixed_key = "XNSim_Access_Key";
|
||
std::vector<unsigned char> key = derive_aes_key(username, fixed_key);
|
||
try {
|
||
std::string accessLevelStr = aes_decrypt(ciphertext, key, iv);
|
||
userInfo["access_level"] = std::stoi(accessLevelStr);
|
||
} catch (...) {
|
||
userInfo["access_level"] = nullptr;
|
||
}
|
||
}
|
||
arr.push_back(userInfo);
|
||
}
|
||
sqlite3_finalize(stmt);
|
||
}
|
||
sqlite3_close(db);
|
||
std::string jsonStr = arr.dump();
|
||
if (result_length >= jsonStr.size() + 1) {
|
||
std::strcpy(result, jsonStr.c_str());
|
||
return 0;
|
||
} else {
|
||
return -1;
|
||
}
|
||
} catch (const std::exception &) {
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
extern "C" LOGIN_EXPORT int deleteUser(int user_id)
|
||
{
|
||
try {
|
||
const char *xnCorePath = std::getenv("XNCore");
|
||
if (!xnCorePath) {
|
||
return -1;
|
||
}
|
||
fs::path dbPath = fs::path(xnCorePath) / "database" / "UserInfo.db";
|
||
sqlite3 *db;
|
||
if (sqlite3_open(dbPath.string().c_str(), &db) != SQLITE_OK) {
|
||
return -1;
|
||
}
|
||
const char *queryStr = "DELETE FROM users WHERE id = ?";
|
||
sqlite3_stmt *stmt;
|
||
if (sqlite3_prepare_v2(db, queryStr, -1, &stmt, nullptr) == SQLITE_OK) {
|
||
sqlite3_bind_int(stmt, 1, user_id);
|
||
if (sqlite3_step(stmt) == SQLITE_DONE) {
|
||
sqlite3_finalize(stmt);
|
||
sqlite3_close(db);
|
||
return 0;
|
||
}
|
||
}
|
||
sqlite3_close(db);
|
||
return -1;
|
||
} catch (const std::exception &) {
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
// 更新用户头像
|
||
extern "C" LOGIN_EXPORT int updateUserIcon(int user_id, const char *icon_base64_buffer,
|
||
int icon_base64_length)
|
||
{
|
||
try {
|
||
if (!icon_base64_buffer || icon_base64_length <= 0) {
|
||
return -1; // 无效的输入参数
|
||
}
|
||
|
||
std::string icon_base64(icon_base64_buffer, icon_base64_length);
|
||
if (icon_base64.empty()) {
|
||
return -1; // 空的Base64数据
|
||
}
|
||
|
||
const char *xnCorePath = std::getenv("XNCore");
|
||
if (!xnCorePath) {
|
||
return -2; // 环境变量未设置
|
||
}
|
||
|
||
fs::path dbPath = fs::path(xnCorePath) / "database" / "UserInfo.db";
|
||
|
||
{
|
||
sqlite3 *db;
|
||
if (sqlite3_open(dbPath.string().c_str(), &db) != SQLITE_OK) {
|
||
return -3; // 数据库连接失败
|
||
}
|
||
|
||
// 首先检查用户是否存在
|
||
sqlite3_stmt *stmt;
|
||
const char *checkQueryStr = "SELECT id FROM users WHERE id = ?";
|
||
|
||
if (sqlite3_prepare_v2(db, checkQueryStr, -1, &stmt, nullptr) == SQLITE_OK) {
|
||
sqlite3_bind_int(stmt, 1, user_id);
|
||
|
||
if (sqlite3_step(stmt) != SQLITE_ROW) {
|
||
sqlite3_finalize(stmt);
|
||
sqlite3_close(db);
|
||
return -4; // 用户不存在
|
||
}
|
||
sqlite3_finalize(stmt);
|
||
}
|
||
|
||
// 将Base64字符串转换为二进制数据
|
||
std::vector<unsigned char> icon_data;
|
||
try {
|
||
icon_data = base64_decode(icon_base64);
|
||
} catch (...) {
|
||
sqlite3_close(db);
|
||
return -5; // Base64解码失败
|
||
}
|
||
|
||
if (icon_data.empty()) {
|
||
sqlite3_close(db);
|
||
return -6; // 解码后数据为空
|
||
}
|
||
|
||
// 更新用户头像
|
||
stmt = nullptr;
|
||
const char *queryStr = "UPDATE users SET icon = ? WHERE id = ?";
|
||
|
||
if (sqlite3_prepare_v2(db, queryStr, -1, &stmt, nullptr) == SQLITE_OK) {
|
||
sqlite3_bind_blob(stmt, 1, icon_data.data(), icon_data.size(), SQLITE_TRANSIENT);
|
||
sqlite3_bind_int(stmt, 2, user_id);
|
||
|
||
if (sqlite3_step(stmt) == SQLITE_DONE) {
|
||
sqlite3_finalize(stmt);
|
||
sqlite3_close(db);
|
||
return 0; // 更新成功
|
||
} else {
|
||
// 获取具体的错误信息
|
||
int error_code = sqlite3_errcode(db);
|
||
const char *error_msg = sqlite3_errmsg(db);
|
||
std::cout << "UPDATE icon failed with error code: " << error_code
|
||
<< ", message: " << (error_msg ? error_msg : "unknown") << std::endl;
|
||
sqlite3_finalize(stmt);
|
||
sqlite3_close(db);
|
||
return -7; // UPDATE语句执行失败
|
||
}
|
||
} else {
|
||
sqlite3_close(db);
|
||
return -8; // UPDATE语句准备失败
|
||
}
|
||
}
|
||
|
||
return -9; // 其他错误
|
||
} catch (const std::exception &) {
|
||
return -10; // 异常错误
|
||
}
|
||
} |