diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index cd6ddcf..b8ab523 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -2650,8 +2650,11 @@ bool CMy2015RemoteDlg::GetEffectiveMasterAddress(std::string& outIP, int& outPor return false; // 使用本地配置 } -// 日期字符串转 Unix 时间戳(当天 23:59:59) -// 输入: "20260323" -> 输出: 1774329599 (2026-03-23 23:59:59 UTC) +// 日期字符串转 Unix 时间戳(当天 23:59:59 UTC) +// 输入: "20260323" -> 输出: 1774310399 (2026-03-23 23:59:59 UTC) +// 必须使用 UTC(_mkgmtime)而非本地时间(mktime)—— 与上级 FrpDateToTimestamp +// 保持一致,否则跨时区的下级算出的 timestamp 与上级生成 privilegeKey 时所用的 +// timestamp 不同,frps 校验失败(token mismatch)。 static time_t DateToTimestamp(const std::string& dateStr) { if (dateStr.length() != 8) return 0; @@ -2661,7 +2664,7 @@ static time_t DateToTimestamp(const std::string& dateStr) t.tm_mon = std::stoi(dateStr.substr(4, 2)) - 1; t.tm_mday = std::stoi(dateStr.substr(6, 2)); t.tm_hour = 23; t.tm_min = 59; t.tm_sec = 59; - return mktime(&t); + return _mkgmtime(&t); } catch (...) { return 0; } diff --git a/server/2015Remote/pwd_gen.cpp b/server/2015Remote/pwd_gen.cpp index 827ae54..842d288 100644 --- a/server/2015Remote/pwd_gen.cpp +++ b/server/2015Remote/pwd_gen.cpp @@ -710,7 +710,10 @@ bool IsFrpTokenEncoded(const std::string& privilegeKey) return privilegeKey.length() >= 4 && privilegeKey.substr(0, 4) == "ENC:"; } -// 日期字符串转 Unix 时间戳(当天 23:59:59 本地时间) +// 日期字符串转 Unix 时间戳(当天 23:59:59 UTC)。 +// 必须使用 UTC(_mkgmtime)而非本地时间(mktime)—— privilegeKey 由上级生成、 +// 下级二次计算后发给 frps 校验,若两端时区不同,mktime 会返回不同的 UTC 时间戳, +// 导致 MD5 不匹配,frps 报 "token in login doesn't match token from configuration"。 time_t FrpDateToTimestamp(const std::string& dateStr) { if (dateStr.length() != 8) return 0; @@ -722,7 +725,7 @@ time_t FrpDateToTimestamp(const std::string& dateStr) t.tm_hour = 23; t.tm_min = 59; t.tm_sec = 59; - return mktime(&t); + return _mkgmtime(&t); } catch (...) { return 0; }