Provide users with a method to change the session ID of a session (#523)
This commit is contained in:
parent
820715cd62
commit
43a21ddc9c
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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_);
|
||||
}
|
||||
}
|
|
@ -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_;
|
||||
|
|
Loading…
Reference in New Issue