tufao
1.3.0
An asynchronous web framework for C++ built on top of Qt
|
SessionStore class can be used to store data that must persist among different requests. More...
Public Member Functions | |
SessionStore (const SessionSettings &settings=defaultSettings(), QObject *parent=0) | |
Constructs a SessionStore object. More... | |
~SessionStore () | |
Destructs a SessionStore object. | |
virtual bool | hasSession (const HttpServerRequest &request) const =0 |
Returns true if a session has been set the request . | |
virtual void | removeSession (const HttpServerRequest &request, HttpServerResponse &response)=0 |
Removes the session, if any, in the request . More... | |
void | resetSession (HttpServerRequest &request) const |
This method removes all cookies matching with this store's settings from request . More... | |
virtual QList< QByteArray > | properties (const HttpServerRequest &request, const HttpServerResponse &response) const =0 |
Returns a list of set properties to this session. More... | |
virtual bool | hasProperty (const HttpServerRequest &request, const HttpServerResponse &response, const QByteArray &key) const =0 |
Returns true if the session has a property named key . More... | |
virtual QVariant | property (const HttpServerRequest &request, HttpServerResponse &response, const QByteArray &key) const =0 |
Returns the property referenced by key in the session, or a null QVariant if the property isn't found. More... | |
virtual void | setProperty (const HttpServerRequest &request, HttpServerResponse &response, const QByteArray &key, const QVariant &value)=0 |
Sets the property's value referenced by key to value . More... | |
virtual void | removeProperty (const HttpServerRequest &request, HttpServerResponse &response, const QByteArray &key)=0 |
Removes the property referenced by key in the session, if any. More... | |
void | setMacSecret (const QByteArray &secret) |
Sets the secret key of the message authentication code. More... | |
Static Public Member Functions | |
static SessionSettings | defaultSettings () |
Returns the default settings, used when you don't specify the settings argument in SessionStore constructor. More... | |
Protected Member Functions | |
QByteArray | session (const HttpServerRequest &request) const |
Returns the value of the first cookie that is compatible with this store's properties, as defined in its settings. More... | |
QByteArray | session (const HttpServerRequest &request, const HttpServerResponse &response) const |
Returns the value of the first cookie that is compatible with this store's properties, as defined in its settings. More... | |
void | setSession (HttpServerResponse &response, const QByteArray &session) const |
Sets a cookie that matches the store's settings in the response object. More... | |
void | unsetSession (HttpServerResponse &response) const |
Invalidates the user's session. More... | |
Protected Attributes | |
SessionSettings | settings |
This attribute represents the session's settings. More... | |
SessionStore class can be used to store data that must persist among different requests.
This is used in web applications, among other, to measure online users, create a shopping list per user and implement a login system.
The session data is stored in properties. You can create a session to any pair of request and response objects and each one will have an independent set of properties.
To access the session properties, you must pass the request and response objects each time you want to manipulate, but this step can be eliminated using the Session helper class.
One session only persists for a specified period of time (set through SessionSettings) and the storage details depends upon the class implementing the SessionStore interface.
To better understand the problems shown in the following subsections, you should understand how cookies works.
A cookie is a piece of text built of a name and a value. The server includes a Set-Cookie header and the user agent will include this cookie in every subsequent request made to this server (when the cookie's scope applies), until the cookie expires.
For example, consider that user U made a request to server S and received the following reply:
HTTP/1.1 200 OK Set-Cookie: Pants=On ...
Then, user U will include the following header in every request made to S:
Cookie: Pants=On
In SessionStore, cookies are abstracted, and they'll be created as needed by some operations. If it finds a valid cookie, it'll use, but if not, it'll create one.
The "valid cookie" term depends on the implementation used.
These attacks exploits applications that allows one user fixate another's user cookie. Consider the following code:
Try to answer: What could happen with an application running the previous code?
Here is what can happens:
How an attacker could set the victim cookie value is out of the scope of this document, because there are several techniques to achieve this.
Never trust users input.
In Tufão, you can defend against session fixation calling SessionStore::resetSession to force a new session to be created.
After the user is authenticated in your application, it can perform some actions, such as transfer money to another account. If it's possible to create a script to automate these actions, then it's possible for an attacker to instruct the victim's user agent to perform this action. An example of a scriptable action is the url below:
http://bank.example.com/withdraw?account=foo&amount=1000000&for=bar
First, you shouldn't allow GET methods to mutate the server's state, but, in this case, use POST wouldn't defend our users against attackers. To prevent our actions from being scriptable, we need to require that an action only will be valid if it's originated from our application.
A technique to achieve the behaviour suggested in the previous paragraph is to generate some random data (a challenge token) and associate it with the user's current session. Then, we insert this token in the pages served to this user. The following code shows part of the solution:
To generate a challenge token, you can use QUuid. To improve this design even further, you can regenerate the token and name parameters for each request.
Yet another option is to requiring the client to provide authentication data in the same request used to perform the action, but this solution add a usability issue.
As defined in RFC 6265 and implemented in browsers, cookies don't provide strong confidentiality. They don't provide:
Cookies don't provide strong integrity also.
You can avoid the previous problems by signing or encrypting cookies, but it'll still be possible for an attacker to perform a replay attack.
You can signing cookies in Tufão using SessionStore::setMacSecret and hide the session data using a SessionStore implementation that don't store its data in the cookie.
See SessionSettings for more information.
If the implementations shipped with Tufão don't supply your needs, you can provide your own storage backend. To do that, you must implement the pure virtual methods of this class. They give you full access to the cookies returned from the user agent and included in the response objects.
The protected methods may help you process and include the cookies. They already take care of the boring task of read and comply with the SessionSettings object and sign the cookies.
This flexible design is what allows you, among other, implement a pure cookie based storage mechanism.
If the application request your store to manipulate some property and the request provides a session's id that don't correspond to any session in the store, you should not reuse this value as an id. You should ignore it and create a new one. This design may add restrictions to some forms of attacks.
|
explicit |
Constructs a SessionStore object.
|
static |
Returns the default settings, used when you don't specify the settings argument in SessionStore constructor.
The default values to these settings are:
If you use more than one store in the same application, you need to set a unique key to each one.
|
pure virtual |
Returns true if the session has a property named key
.
The session is represented by the pair request
, response
.
Implemented in Tufao::SimpleSessionStore.
|
pure virtual |
Returns a list of set properties to this session.
The session is represented by the pair request
, response
.
Implemented in Tufao::SimpleSessionStore.
|
pure virtual |
Returns the property referenced by key
in the session, or a null QVariant if the property isn't found.
The session is represented by the pair request
, response
.
Implemented in Tufao::SimpleSessionStore.
|
pure virtual |
Removes the property referenced by key
in the session, if any.
The session is represented by the pair request
, response
.
Implemented in Tufao::SimpleSessionStore.
|
pure virtual |
Removes the session, if any, in the request
.
Implemented in Tufao::SimpleSessionStore.
void Tufao::SessionStore::resetSession | ( | HttpServerRequest & | request | ) | const |
This method removes all cookies matching with this store's settings from request
.
The purpose is hide the cookies from other pieces of code handling request
.
Call this if you need to reset the session id.
|
protected |
Returns the value of the first cookie that is compatible with this store's properties, as defined in its settings.
|
protected |
Returns the value of the first cookie that is compatible with this store's properties, as defined in its settings.
Besides searching in the request's
headers named as "Cookie", search in response's
headers named as "Set-Cookie". This allows you to manipulate sessions as soon as they are set.
void Tufao::SessionStore::setMacSecret | ( | const QByteArray & | secret | ) |
Sets the secret key of the message authentication code.
If set, it will protects the cookies integrity and authenticity.
The algorithm used by Tufão is HMAC + SHA1.
|
pure virtual |
Sets the property's value referenced by key
to value
.
The session is represented by the pair request
, response
.
Implemented in Tufao::SimpleSessionStore.
|
protected |
Sets a cookie that matches the store's settings in the response
object.
response
object has undefined behaviour.
|
protected |
Invalidates the user's session.
This is done by setting the expiration date to the past, as specified by RFC 6265.
|
protected |
This attribute represents the session's settings.
It will be used in the operations involving cookie's handling and is set automatically in SessionStore's constructor.