106 lines
3.0 KiB
C++
106 lines
3.0 KiB
C++
#include "SessionStore.h"
|
|
#include <boost/uuid/uuid_generators.hpp>
|
|
#include <boost/uuid/uuid_io.hpp>
|
|
namespace Older {
|
|
SessionStore::SessionStore(boost::asio::io_context &ioContext) : m_ioContext(ioContext), m_cleanupTimer(ioContext) {
|
|
startCleanupTask();
|
|
}
|
|
|
|
std::string SessionStore::addSession(int userId, std::chrono::minutes sessionLifetime, std::chrono::minutes refreshInterval) {
|
|
using namespace boost::uuids;
|
|
using namespace std::chrono;
|
|
std::unique_lock lock(m_mutex);
|
|
|
|
random_generator uuid_gen;
|
|
auto now = system_clock::now();
|
|
|
|
SessionData data{userId,
|
|
to_string(uuid_gen()), // 生成刷新令牌
|
|
now + sessionLifetime, now + refreshInterval};
|
|
|
|
std::string access_token = to_string(uuid_gen());
|
|
m_sessions[access_token] = data;
|
|
|
|
m_refreshMap[data.refreshToken] = access_token;
|
|
|
|
return access_token;
|
|
}
|
|
|
|
void SessionStore::removeSession(const std::string &token) {
|
|
std::unique_lock lock(m_mutex);
|
|
auto it = m_sessions.find(token);
|
|
if (it != m_sessions.end()) {
|
|
m_refreshMap.erase(it->second.refreshToken);
|
|
m_sessions.erase(it);
|
|
}
|
|
}
|
|
|
|
std::pair<bool, std::string> SessionStore::validateAndRefresh(const std::string &token) {
|
|
using namespace std::chrono;
|
|
using namespace boost::uuids;
|
|
std::unique_lock lock(m_mutex);
|
|
auto it = m_sessions.find(token);
|
|
if (it == m_sessions.end()) return {false, ""};
|
|
|
|
auto now = system_clock::now();
|
|
SessionData &data = it->second;
|
|
|
|
if (now > data.expireTime) { // 检查是否过期
|
|
m_sessions.erase(it);
|
|
m_refreshMap.erase(data.refreshToken);
|
|
return {false, ""};
|
|
}
|
|
|
|
std::string newToken = token;
|
|
if (now > data.refreshTime) { // 检查是否需要刷新
|
|
random_generator uuid_gen;
|
|
newToken = to_string(uuid_gen());
|
|
|
|
// 保留刷新令牌
|
|
SessionData newData = data;
|
|
newData.refreshTime = now + minutes{15};
|
|
|
|
m_sessions.erase(it);
|
|
m_sessions[newToken] = newData;
|
|
|
|
m_refreshMap[data.refreshToken] = newToken;
|
|
}
|
|
|
|
return {true, newToken};
|
|
}
|
|
|
|
SessionData SessionStore::at(const std::string &token) {
|
|
SessionData ret;
|
|
if (m_sessions.count(token) > 0) {
|
|
ret = m_sessions.at(token);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void SessionStore::startCleanupTask() {
|
|
using namespace std::chrono_literals;
|
|
m_cleanupTimer.expires_after(5min);
|
|
m_cleanupTimer.async_wait([this](boost::system::error_code ec) {
|
|
if (!ec) {
|
|
cleanupExpiredSessions();
|
|
startCleanupTask();
|
|
}
|
|
});
|
|
}
|
|
|
|
void SessionStore::cleanupExpiredSessions() {
|
|
using namespace std::chrono;
|
|
std::unique_lock lock(m_mutex);
|
|
auto now = system_clock::now();
|
|
|
|
for (auto it = m_sessions.begin(); it != m_sessions.end();) {
|
|
if (now > it->second.expireTime) {
|
|
m_refreshMap.erase(it->second.refreshToken);
|
|
it = m_sessions.erase(it);
|
|
} else {
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace Older
|