QtWebApp
httpsessionstore.cpp
Go to the documentation of this file.
1 
6 #include "httpsessionstore.h"
7 #include <QDateTime>
8 #include <QUuid>
9 
10 using namespace stefanfrings;
11 
12 HttpSessionStore::HttpSessionStore(const QSettings *settings, QObject* parent)
13  :QObject(parent)
14 {
15  this->settings=settings;
16  connect(&cleanupTimer,SIGNAL(timeout()),this,SLOT(sessionTimerEvent()));
17  cleanupTimer.start(60000);
18  cookieName=settings->value("cookieName","sessionid").toByteArray();
19  expirationTime=settings->value("expirationTime",3600000).toInt();
20  qDebug("HttpSessionStore: Sessions expire after %i milliseconds",expirationTime);
21 }
22 
24 {
25  cleanupTimer.stop();
26 }
27 
29 {
30  // The session ID in the response has priority because this one will be used in the next request.
31  mutex.lock();
32  // Get the session ID from the response cookie
33  QByteArray sessionId=response.getCookies().value(cookieName).getValue();
34  if (sessionId.isEmpty())
35  {
36  // Get the session ID from the request cookie
37  sessionId=request.getCookie(cookieName);
38  }
39  // Clear the session ID if there is no such session in the storage.
40  if (!sessionId.isEmpty())
41  {
42  if (!sessions.contains(sessionId))
43  {
44  qDebug("HttpSessionStore: received invalid session cookie with ID %s",sessionId.data());
45  sessionId.clear();
46  }
47  }
48  mutex.unlock();
49  return sessionId;
50 }
51 
52 HttpSession HttpSessionStore::getSession(HttpRequest& request, HttpResponse& response, bool allowCreate)
53 {
54  QByteArray sessionId=getSessionId(request,response);
55  mutex.lock();
56  if (!sessionId.isEmpty())
57  {
58  HttpSession session=sessions.value(sessionId);
59  if (!session.isNull())
60  {
61  mutex.unlock();
62  // Refresh the session cookie
63  QByteArray cookieName=settings->value("cookieName","sessionid").toByteArray();
64  QByteArray cookiePath=settings->value("cookiePath").toByteArray();
65  QByteArray cookieComment=settings->value("cookieComment").toByteArray();
66  QByteArray cookieDomain=settings->value("cookieDomain").toByteArray();
67  response.setCookie(HttpCookie(cookieName,session.getId(),expirationTime/1000,
68  cookiePath,cookieComment,cookieDomain,false,false,"Lax"));
69  session.setLastAccess();
70  return session;
71  }
72  }
73  // Need to create a new session
74  if (allowCreate)
75  {
76  QByteArray cookieName=settings->value("cookieName","sessionid").toByteArray();
77  QByteArray cookiePath=settings->value("cookiePath").toByteArray();
78  QByteArray cookieComment=settings->value("cookieComment").toByteArray();
79  QByteArray cookieDomain=settings->value("cookieDomain").toByteArray();
80  HttpSession session(true);
81  qDebug("HttpSessionStore: create new session with ID %s",session.getId().data());
82  sessions.insert(session.getId(),session);
83  response.setCookie(HttpCookie(cookieName,session.getId(),expirationTime/1000,
84  cookiePath,cookieComment,cookieDomain,false,false,"Lax"));
85  mutex.unlock();
86  return session;
87  }
88  // Return a null session
89  mutex.unlock();
90  return HttpSession();
91 }
92 
94 {
95  mutex.lock();
96  HttpSession session=sessions.value(id);
97  mutex.unlock();
98  session.setLastAccess();
99  return session;
100 }
101 
102 void HttpSessionStore::sessionTimerEvent()
103 {
104  mutex.lock();
105  qint64 now=QDateTime::currentMSecsSinceEpoch();
106  QMap<QByteArray,HttpSession>::iterator i = sessions.begin();
107  while (i != sessions.end())
108  {
109  QMap<QByteArray,HttpSession>::iterator prev = i;
110  ++i;
111  HttpSession session=prev.value();
112  qint64 lastAccess=session.getLastAccess();
113  if (now-lastAccess>expirationTime)
114  {
115  qDebug("HttpSessionStore: session %s expired",session.getId().data());
116  emit sessionDeleted(session.getId());
117  sessions.erase(prev);
118  }
119  }
120  mutex.unlock();
121 }
122 
123 
126 {
127  mutex.lock();
128  emit sessionDeleted(session.getId());
129  sessions.remove(session.getId());
130  mutex.unlock();
131 }
HTTP cookie as defined in RFC 2109.
Definition: httpcookie.h:21
This object represents a single HTTP request.
Definition: httprequest.h:37
QByteArray getCookie(const QByteArray &name) const
Get the value of a cookie.
This object represents a HTTP response, used to return something to the web client.
Definition: httpresponse.h:36
QMap< QByteArray, HttpCookie > & getCookies()
Get the map of cookies.
void setCookie(const HttpCookie &cookie)
Set a cookie.
virtual ~HttpSessionStore()
Destructor.
QMap< QByteArray, HttpSession > sessions
Storage for the sessions.
void removeSession(const HttpSession session)
Delete a session.
HttpSessionStore(const QSettings *settings, QObject *parent=nullptr)
Constructor.
QByteArray getSessionId(HttpRequest &request, HttpResponse &response)
Get the ID of the current HTTP session, if it is valid.
void sessionDeleted(const QByteArray &sessionId)
Emitted when the session is deleted.
HttpSession getSession(HttpRequest &request, HttpResponse &response, const bool allowCreate=true)
Get the session of a HTTP request, eventually create a new one.
This class stores data for a single HTTP session.
Definition: httpsession.h:23
bool isNull() const
Null sessions cannot store data.
void setLastAccess()
Set the timestamp of last access, to renew the timeout period.
QByteArray getId() const
Get the unique ID of this session.
Definition: httpsession.cpp:95
qint64 getLastAccess() const
Get the timestamp of last access.