Improve: client/server - stable client ID via MachineGuid+path (V2)
This commit is contained in:
@@ -214,6 +214,54 @@ static std::string getUsername()
|
||||
return user ? std::string(user) : "unknown";
|
||||
}
|
||||
|
||||
// 读取 IOKit 维护的 IOPlatformUUID(与 Windows MachineGuid 等价)
|
||||
// 这是主板/系统级 UUID,由 IOPlatformExpertDevice 服务提供,重装系统通常不变。
|
||||
// 对应:Windows HKLM\Software\Microsoft\Cryptography\MachineGuid
|
||||
// Linux /etc/machine-id
|
||||
static std::string getMachineId()
|
||||
{
|
||||
std::string result;
|
||||
io_service_t platformExpert = IOServiceGetMatchingService(
|
||||
kIOMasterPortDefault,
|
||||
IOServiceMatching("IOPlatformExpertDevice"));
|
||||
if (platformExpert != IO_OBJECT_NULL) {
|
||||
CFTypeRef uuidProperty = IORegistryEntryCreateCFProperty(
|
||||
platformExpert, CFSTR(kIOPlatformUUIDKey),
|
||||
kCFAllocatorDefault, 0);
|
||||
if (uuidProperty != nullptr) {
|
||||
if (CFGetTypeID(uuidProperty) == CFStringGetTypeID()) {
|
||||
CFStringRef uuidStr = (CFStringRef)uuidProperty;
|
||||
char buf[64] = {};
|
||||
if (CFStringGetCString(uuidStr, buf, sizeof(buf), kCFStringEncodingUTF8)) {
|
||||
result = buf;
|
||||
}
|
||||
}
|
||||
CFRelease(uuidProperty);
|
||||
}
|
||||
IOObjectRelease(platformExpert);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// 路径归一化(macOS 版):解析符号链接 + 转小写
|
||||
// realpath 把 /Applications/foo/../bar 之类折回规范形式;
|
||||
// 小写化保持与 Windows/Linux 跨端一致。macOS HFS+/APFS 默认大小写不敏感,
|
||||
// 转小写不改变文件标识、但避免路径串大小写差异引起 ID 不同。
|
||||
static std::string normalizeExePathLower(const std::string& path)
|
||||
{
|
||||
char resolved[PATH_MAX] = {};
|
||||
std::string out;
|
||||
if (realpath(path.c_str(), resolved) != nullptr) {
|
||||
out = resolved;
|
||||
} else {
|
||||
out = path; // 解析失败:用原值
|
||||
}
|
||||
for (auto& c : out) {
|
||||
if (c >= 'A' && c <= 'Z') c = c - 'A' + 'a';
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Get screen resolution
|
||||
static std::string getScreenResolution()
|
||||
{
|
||||
@@ -552,16 +600,30 @@ static void fillLoginInfo(LOGIN_INFOR& info)
|
||||
std::string resolution = getScreenResolution();
|
||||
info.AddReserved(resolution.c_str());
|
||||
|
||||
// 17. Client ID (calculated from system info, same algorithm as server)
|
||||
// Format: pubIP|hostname|os|cpu|path
|
||||
char cpuStr[32];
|
||||
snprintf(cpuStr, sizeof(cpuStr), "%uMHz", info.dwCPUMHz);
|
||||
std::string idInput = (pubIP.empty() ? "?" : pubIP) + "|" +
|
||||
hostname + "|" +
|
||||
osVer + "|" +
|
||||
cpuStr + "|" +
|
||||
exePath;
|
||||
g_myClientID = XXH64(idInput.c_str(), idInput.length(), 0);
|
||||
// 17. Client ID
|
||||
// V2 算法:IOPlatformUUID + 归一化路径
|
||||
// - 同机同程序路径永远同 ID(不依赖 IP/hostname/os/CPU 漂移)
|
||||
// - IOPlatformUUID 主板级,重装系统通常不变;多机各不相同
|
||||
// - 读取失败时退化到老算法(pubIP|hostname|os|cpu|path)保兼容
|
||||
std::string machineId = getMachineId();
|
||||
if (!machineId.empty()) {
|
||||
std::string normPath = normalizeExePathLower(exePath);
|
||||
std::string idInput = machineId + "|" + normPath;
|
||||
g_myClientID = XXH64(idInput.c_str(), idInput.length(), 0);
|
||||
NSLog(@"ClientID(v2): %llu (machineId=%s, path=%s)",
|
||||
g_myClientID, machineId.c_str(), normPath.c_str());
|
||||
} else {
|
||||
// 老算法兜底
|
||||
char cpuStr[32];
|
||||
snprintf(cpuStr, sizeof(cpuStr), "%uMHz", info.dwCPUMHz);
|
||||
std::string idInput = (pubIP.empty() ? "?" : pubIP) + "|" +
|
||||
hostname + "|" +
|
||||
osVer + "|" +
|
||||
cpuStr + "|" +
|
||||
exePath;
|
||||
g_myClientID = XXH64(idInput.c_str(), idInput.length(), 0);
|
||||
NSLog(@"ClientID(v1 fallback): %llu (IOPlatformUUID 读取失败)", g_myClientID);
|
||||
}
|
||||
info.AddReserved(std::to_string(g_myClientID).c_str());
|
||||
|
||||
NSLog(@"LOGIN_INFOR filled: OS=%s, Host=%s, CPU=%dMHz, PubIP=%s, ClientID=%llu",
|
||||
|
||||
Reference in New Issue
Block a user