Genivia Home Documentation
The Sessions Plugin

updated Wed Aug 17 2016
 
The Sessions Plugin

Table of Contents

HTTP Server Session Management Plugin

By Chris Moutsos and Robert van Engelen.

Overview

The HTTP server session management plugin for gSOAP enables servers to store a database of sessions to keep track of client data across multiple requests. Client data is stored per session as name and value pairs that can be set to any valid string. Sessions are tracked with unique session IDs (sometimes called tokens) that are passed between the server and client with HTTP cookies.

The sessions plugin is MT safe.

Features

Setup

To set up the sessions plugin on the server-side:

  1. Make sure to compile your program with plugin/sessions.c and plugin/threads.c.
  2. Enable cookies by compiling all gSOAP source code with -DWITH_COOKIES. Cookies are required for tracking session IDs.
  3. Enable HTTPS (compile with -DWITH_OPENSSL or -DWITH_GNUTLS or link with -lgsoapssl/-lgsoapssl++).
Note
While it is not a requirement to use HTTPS with this plugin, it is strongly recommended to use HTTPS. This is because the session ID cookies can be intercepted if not encrypted with SSL/TLS. Cookies are automatically sent with the Secure flag enabled when SSL is enabled. The HttpOnly flag is automatically enabled for all cookies in order to prevent XSS attacks.

Basic Usage

Client-side usage is automatic, provided that the client supports cookies and the server has properly configured the plugin. If the client is a gSOAP application, make sure to compile with -DWITH_COOKIES.

For server-side usage, register the plugin with:

struct soap *soap = soap_new();
soap_register_plugin(soap, sessions);

If you are using a server object in C++ generated with soappcpp2 option -j:

soap_register_plugin(server.soap, sessions);

For brevity, the struct soap* version will be used below. Replace soap with your server object's soap member if necessary.

Start a new session with:

struct soap_session *session = soap_start_session(soap, "domain", "path");

This creates a new session with a random 128-bit session ID and the default settings (see section: Settings). If the client already has a session ID cookie with name SESSION_COOKIE_NAME and the given domain and path, and that ID refers to a valid session, that existing session will be returned instead.

Note
For all of the sessions plugin function calls, domain and path arguments are required. These must match the values that were given when the session was created, otherwise the client's session ID cookie won't be found. The domain and path arguments may be set to NULL to use the current values given by the soap context's cookie_domain and cookie_path members:
Attribute Value
const char *cookie_domain MUST be set to the domain (host) of the service
const char *cookie_path MAY be set to the default path to the service (defaults to '/')
These rules also apply to the cookies used for tracking session IDs. See the gSOAP User Guide for more information on how gSOAP handles cookies.

For example, to create a session on localhost:8080 that is valid on any path:

soap->cookie_domain = "localhost:8080";
struct soap_session *session = soap_start_session(soap, NULL, NULL);

To create a new session variable or modify an existing session variable inside that session:

soap_set_session_var(soap, "session_var_name", "session_var_value", NULL, NULL);

To access the value of that session variable:

const char *value = soap_get_session_var(soap, "session_var_name", NULL, NULL);

To delete that session variable:

soap_clr_session_var(soap, "session_var_name", NULL, NULL);

Consider changing the session's rolling, cookie_maxage, max_inactive_secs settings from their defaults. Read more about these in the Settings section.

Simple Calculator Server (C) Example

We will show how to extend the simple calculator server example (in C) to keep track of the client's last calculated value with a session variable.

Make sure to register the plugin and set the default domain and path. After calling soap_destroy and soap_end, we should also free the internal cookie database (or call soap_done):

#include "plugin/session.h"
...
struct soap soap;
soap_init(&soap);
soap_register_plugin(&soap, sessions);
soap.cookie_domain = "localhost:8080";
soap.cookie_path = "/";
... // set up the service and serve requests
soap_destroy(&soap);
soap_end(&soap);
soap_free_cookies(&soap);

Now in each of our calculator service operations (ns__add, ns__sub, etc.), we can update the lastCalculation session variable in our current session:

int ns__add(struct soap *soap, double a, double b, double *result)
{
(void)soap; *result = a + b;
// make sure we have a session
if (!soap_get_session(soap, NULL, NULL))
{
// no current session, create a new one
if (!soap_start_session(soap, NULL, NULL))
return SOAP_ERR; // session creation failed
// configure session settings
soap_set_session_rolling(soap, 1, NULL, NULL);
soap_set_session_cookie_maxage(soap, 30, NULL, NULL);
soap_set_session_max_inactive_secs(soap, 30, NULL, NULL);
}
// update `lastCalculation` session variable
char calculation[80];
sprintf(calculation, "add %f %f, result = %f", a, b, *result);
soap_set_session_var(soap, "lastCalculation", calculation, NULL, NULL);
return SOAP_OK;
}

If we want to allow the client to access their last calculation, add another service operation to retrieve the lastCalculation session variable:

int ns__getLastCalculation(struct soap *soap, char **r)
{
const char *lastCalculation = soap_get_session_var(soap, "lastCalculation", NULL, NULL);
if (!lastCalculation)
lastCalculation = "None";
if ((*r = (char*)soap_malloc(soap, strlen(lastCalculation)+1)))
strcpy(*r, lastCalculation);
return SOAP_OK;
}

Sessions Plugin API

This section describes the Sessions Plugin API.

Note
The term session ID cookie refers to a cookie with the name SESSION_COOKIE_NAME (see section: Settings), the given domain and path (see section: Basic Usage), and a random 128-bit session ID as the value. The term current session refers to the session in the database identified by the client's session ID cookie.
The arguments domain and path may be set to NULL to use the current values given by soap->cookie_domain and soap->cookie_path (see section: Basic Usage).

The sessions plugin provides the following API for server-side session management:

Session Plugin Function Description
struct soap_session* soap_start_session(struct soap * soap, const char *domain, const char *path);
Create a session in the database and a session ID cookie. Behaves the same as soap_get_session if the client already has a valid session ID cookie. Returns pointer to the session node, or NULL if the session could not be created.
struct soap_session* soap_get_session(struct soap *soap, const char *domain, const char *path);
Get the current session. Can be used as a 'touch'. Returns pointer to the session node, or NULL if the session is not found or is expired.
int soap_get_num_sessions(struct soap *soap, const char *domain, const char *path);
Get the number of sessions in the database. Returns -1 if the session is not found or is expired.
struct soap_session* soap_regenerate_session_id(struct soap * soap, const char *domain, const char *path);
Create a new session ID for the current session and update the session ID cookie. Returns pointer to the session node, or NULL if the session is not found or is expired.
int soap_get_num_session_vars(struct soap *soap, const char *domain, const char *path);
Get the number of session variables in the current session. Returns -1 if the session is not found or is expired.
void soap_end_session(struct soap *soap, const char * domain, const char *path);
Delete the current session from the database and clear the client's session ID cookie.
void soap_end_sessions(struct soap *soap, const char * domain, const char *path);
Delete all sessions in the database and clear the current session ID cookie.
struct soap_session_var* soap_set_session_var(struct soap * soap, const char *name, const char *value, const char domain, const char *path);
Set a session variable with the given name and value in the current session, overwring any old value. Returns pointer to the session variable node, or NULL if the session is not found or is expired.
const char* soap_get_session_var(struct soap *soap, const char *name, const char *domain, const char *path);
Get the value of the session variable with the given name in the current session. Returns NULL if the session is not found or is expired.
void soap_clr_session_var(struct soap *soap, const char *name, const char *domain, const char *path);
Delete the session variable with the given name in the current session.
void soap_clr_session_vars(struct soap *soap, const char *domain, const char *path);
Delete all session variables in the current session.

For managing session settings (see section: Settings), the following API is provided:

Session Plugin Function Description (Settings / Misc.)
int soap_set_session_rolling(struct soap * soap, int rolling, const char *domain, const char * path);
Set the rolling setting for the current session. Zero (non-rolling) means the session ID cookie is only set when the session is first created. Non-zero (rolling) means the session ID cookie will be re-set on every response. If successful, returns SOAP_OK, or SOAP_ERR otherwise.
int soap_get_session_rolling(struct soap * soap, const char *domain, const char *path);
Get the rolling setting for the current session. Returns -1 if the session is not found or is expired.
int soap_set_session_cookie_maxage(struct soap * soap, long maxage, const char *domain, const char * path);
Set the cookie_maxage member for the current session. This will be used to set the session ID cookie's Max-Age and Expires attributes. -1 means the cookie will have no Max-Age or Expires attributes. If successful, returns SOAP_OK, or SOAP_ERR otherwise.
long soap_get_session_cookie_maxage(struct soap * soap, const char *domain, const char *path);
Get the cookie_maxage member for the current session. Returns 0 if the session is not found or is expired.
int soap_set_session_max_inactive_secs(struct soap * soap, long max, const char *domain, const char * path);
Set the max_inactive_secs member for the current session. This is the maximum amount of stale time in seconds before a session is marked as expired (to be purged) on the server-side. -1 means the session will never expire. If successful, returns SOAP_OK, or SOAP_ERR otherwise.
long soap_get_session_max_inactive_secs(struct soap * soap, const char *domain, const char *path);
Get the max_inactive_secs member for the current session. Returns 0 if the session is not found or is expired.
struct soap_session* soap_get_sessions_head();
Get soap_sessions, the first node in the sessions linked list. Not necessary unless low-level list management is needed (see section: The Internals).

Settings

In plugins/session.h, the following constants are defined:

Name Default Description
SESSION_COOKIE_NAME "GSOAP_SESSIONID" The name to use for session ID cookies.
SESSION_MAX 8192 The max number of sessions allowed in the database. Any attempt to create more sessions than this will fail.
SESSIONS_DEFAULT_MAX_INACTIVE_SECS 300 The default time in seconds for sessions' max_inactive_secs member. -1 means the session will never expire server-side.
SESSION_PURGE_INTERVAL 300 On every session database access, the time since the last database purge is checked. If it's been longer than this interval (in seconds), any expired sessions will be purged with soap_purge_sessions(). 0 means a purge will occcur on every database access. -1 means a purge will never occur.

Set these values to whatever makes sense for your application.

In each session node, the following settings are declared:

Name Default Description
rolling 0 Non-rolling (0) means the session ID cookie is only set when the session is first created. Rolling (non-0) means the session ID cookie will be re-set on every response after any part of the session has been touched.
cookie_maxage -1 This will be used to set the session ID cookie's Max-Age and Expires attributes. -1 means the cookie will have no Max-Age or Expires attributes.
max_inactive_secs SESSIONS_DEFAULT_MAX_INACTIVE_SECS This is the maximum amount of stale time in seconds before a session is marked as expired (to be purged) on the server-side. -1 means the session will never expire server-side. This should probably be set equal to cookie_maxage unless that value is -1.
Note
These settings should not be changed directly. See the Sessions Plugin API section for functions to manage these settings.

The Internals

The session database is stored as a linked list pointed to by soap_sessions (accessible by calling soap_get_sessions_head()). Session nodes are of type struct soap_session and are declared as:

{
struct soap_session *next;
const char *id;
int num_session_vars; // the total number of session_vars we have in this session
long cookie_maxage; // client time in seconds before the cookie expires (-1 for session cookie)
int rolling; // whether or not we should set the cookie's maxage on every response
time_t last_touched; // time that we last touched this session or its vars
long max_inactive_secs; // server time in seconds before inactive session expires (-1 to never expire)
// this should usually be at least as high as cookie_maxage
};

The session_vars member is a pointer to the session's linked list of session variables. Session variable nodes are of type struct soap_session_var and are declared as:

{
const char *name;
const char *value;
};