#include "Credential.hpp" #include #include #include namespace geopro::app { namespace { const QString kService = QStringLiteral("Geopro3"); const QString kKey = QStringLiteral("session"); // QtKeychain 的 job 是异步的;用局部事件循环跑成同步(启动/登录时一次性调用,可接受)。 QString readRaw() { QKeychain::ReadPasswordJob job(kService); job.setAutoDelete(false); job.setKey(kKey); QEventLoop loop; QObject::connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.start(); loop.exec(); if (job.error() != QKeychain::NoError) return {}; return job.textData(); } } // namespace void rememberSession(const QString& token) { if (token.isEmpty()) return; const QString payload = QString::number(QDateTime::currentSecsSinceEpoch()) + QStringLiteral("|") + token; QKeychain::WritePasswordJob job(kService); job.setAutoDelete(false); job.setKey(kKey); job.setTextData(payload); QEventLoop loop; QObject::connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.start(); loop.exec(); } QString recallValidToken(int maxAgeDays) { const QString raw = readRaw(); if (raw.isEmpty()) return {}; const int sep = raw.indexOf(QLatin1Char('|')); if (sep <= 0) return {}; bool ok = false; const qint64 ts = raw.left(sep).toLongLong(&ok); if (!ok) return {}; const qint64 ageSec = QDateTime::currentSecsSinceEpoch() - ts; if (ageSec < 0 || ageSec > static_cast(maxAgeDays) * 24 * 3600) return {}; return raw.mid(sep + 1); } void forgetSession() { QKeychain::DeletePasswordJob job(kService); job.setAutoDelete(false); job.setKey(kKey); QEventLoop loop; QObject::connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.start(); loop.exec(); } } // namespace geopro::app