Provide users with a method to change the session ID of a session (#523)

This commit is contained in:
An Tao 2020-08-03 19:18:47 +08:00 committed by GitHub
parent 820715cd62
commit 43a21ddc9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 96 additions and 23 deletions

View File

@ -303,6 +303,26 @@ class CacheMap
return loop_;
}
/**
* @brief run the task function after a period of time.
*
* @param delay in seconds
* @param task
* @note This timer is a low-precision timer whose accuracy depends on the
* tickInterval parameter of the cache. The advantage of the timer is its
* low cost.
*/
void runAfter(size_t delay, std::function<void()> &&task)
{
std::lock_guard<std::mutex> lock(bucketMutex_);
insertEntry(delay, std::make_shared<CallbackEntry>(std::move(task)));
}
void runAfter(size_t delay, const std::function<void()> &task)
{
std::lock_guard<std::mutex> lock(bucketMutex_);
insertEntry(delay, std::make_shared<CallbackEntry>(task));
}
private:
std::unordered_map<T1, MapValue> map_;
@ -394,10 +414,8 @@ class CacheMap
}
}
};
entryPtr = std::make_shared<CallbackEntry>(cb);
entryPtr = std::make_shared<CallbackEntry>(std::move(cb));
map_[key].weakEntryPtr_ = entryPtr;
{
std::lock_guard<std::mutex> lock(bucketMutex_);
insertEntry(delay, entryPtr);

View File

@ -34,6 +34,10 @@ class Cookie
: key_(key), value_(value)
{
}
Cookie(std::string &&key, std::string &&value)
: key_(std::move(key)), value_(std::move(value))
{
}
Cookie() = default;
/**

View File

@ -127,32 +127,21 @@ class Session
/**
* @brief Get the session ID of the current session.
*/
const std::string &sessionId() const
std::string sessionId() const
{
std::lock_guard<std::mutex> lck(mutex_);
return sessionId_;
}
/**
* @brief If the session ID needs to be set to the client through cookie,
* return true
* @brief Let the framework create a new session ID for this session and set
* it to the client.
* @note This method does not change the session ID now.
*/
bool needSetToClient() const
{
return needToSet_;
}
/**
* @brief Change the state of the session, usually called by the framework
*/
void hasSet()
{
needToSet_ = false;
}
/**
* @brief Constructor, usually called by the framework
*/
Session(const std::string &id, bool needToSet)
: sessionId_(id), needToSet_(needToSet)
void changeSessionIdToClient()
{
needToChange_ = true;
needToSet_ = true;
}
Session() = delete;
@ -162,6 +151,44 @@ class Session
mutable std::mutex mutex_;
std::string sessionId_;
bool needToSet_{false};
bool needToChange_{false};
friend class SessionManager;
friend class HttpAppFrameworkImpl;
/**
* @brief Constructor, usually called by the framework
*/
Session(const std::string &id, bool needToSet)
: sessionId_(id), needToSet_(needToSet)
{
}
/**
* @brief Change the state of the session, usually called by the framework
*/
void hasSet()
{
needToSet_ = false;
}
/**
* @brief If the session ID needs to be changed.
*
*/
bool needToChangeSessionId() const
{
return needToChange_;
}
/**
* @brief If the session ID needs to be set to the client through cookie,
* return true
*/
bool needSetToClient() const
{
return needToSet_;
}
void setSessionId(const std::string &id)
{
std::lock_guard<std::mutex> lck(mutex_);
sessionId_ = id;
}
};
using SessionPtr = std::shared_ptr<Session>;

View File

@ -686,6 +686,10 @@ void HttpAppFrameworkImpl::callCallback(
{
auto sessionPtr = req->getSession();
assert(sessionPtr);
if (sessionPtr->needToChangeSessionId())
{
sessionManagerPtr_->changeSessionId(sessionPtr);
}
if (sessionPtr->needSetToClient())
{
if (resp->expiredTime() >= 0)

View File

@ -13,6 +13,7 @@
*/
#include "SessionManager.h"
#include <drogon/utils/Utilities.h>
using namespace drogon;
@ -57,9 +58,27 @@ SessionPtr SessionManager::getSession(const std::string &sessionID,
std::lock_guard<std::mutex> lock(mapMutex_);
if (sessionMapPtr_->findAndFetch(sessionID, sessionPtr) == false)
{
sessionPtr = std::make_shared<Session>(sessionID, needToSet);
sessionPtr =
std::shared_ptr<Session>(new Session(sessionID, needToSet));
sessionMapPtr_->insert(sessionID, sessionPtr, timeout_);
return sessionPtr;
}
return sessionPtr;
}
void SessionManager::changeSessionId(const SessionPtr &sessionPtr)
{
auto oldId = sessionPtr->sessionId();
auto newId = utils::getUuid();
sessionPtr->setSessionId(newId);
{
std::lock_guard<std::mutex> lock(mapMutex_);
// For requests sent before setting the new session ID to the client, we
// reserve the old session slot for a period of time.
sessionMapPtr_->runAfter(10, [this, oldId = std::move(oldId)]() {
LOG_TRACE << "remove the old slot of the session";
sessionMapPtr_->erase(oldId);
});
sessionMapPtr_->insert(newId, sessionPtr, timeout_);
}
}

View File

@ -33,6 +33,7 @@ class SessionManager : public trantor::NonCopyable
sessionMapPtr_.reset();
}
SessionPtr getSession(const std::string &sessionID, bool needToSet);
void changeSessionId(const SessionPtr &sessionPtr);
private:
std::unique_ptr<CacheMap<std::string, SessionPtr>> sessionMapPtr_;