session module

Synopsis

The session module provides way to group HTTP requests into "sessions" so that information can be maintained between an individual user's requests to various parts of a web site - for example, so that a user can "log in" to the web site and their username remembered as they navigate the site.

Usage

The base Session class is not used directly, since it has no way of storing the data associated with a session. Instead, one of the classes derived from it are used. The choice of subclass determines what storage method is used - the module provides FileSession and GenericSQLSession, or you can write your own.

To store data in the session, you simply use it as a mapping. For example:

if "basket" in self.session:
  self.session["basket"].append(newitem)
else:
  self.session["basket"] = [newitem]

Sessions are identified by a unique 8-character hexadecimal string, which is usually generated randomly. This is paired with another 8-character hexadecimal string which is a keyed hash generated using the identifier and a secret key unique to the individual web site. The hash simply makes it a bit more difficult for an attacker to guess a valid session identifier. The id and hash are stored in the session under the keys id and hash, so don't try to use these keys for storing your own data.

The session identifier and hash are passed from request to request using cookies. Note that some users disable cookies in their browsers, so site code will need to detect this situation and either cope without sessions, or show the user an error message.

This module used to provide a method for embedding the session identifier in the URL, but this has now been deprecated.

To create and maintain the session, a session class should be instantiated at the start of processing a request, and its save method called at the end of processing.

Example:

class Handler(wt.Handler):
  def process(self, req):
    self.session = session.FileSession(req, "s3cr3t")
    if not self.session.relocated:
      wt.Handler.process(self, req)
      self.session.save()

class: Error(Exception)

The base class for all exceptions defined by the session module.

class: Session(dict)

Session objects manage the session as well as providing a container to store data associated with the session. This class is not used directly, but is subclassed depending on what method is being used to store the session data.

Public Instance Variables

created

The number of seconds since the epoch (i.e. time.time() value) when this session was created.

new

new references a true value if the session was created during this request (i.e. there was no pre-existing session).

Public Methods

__init__(self, req, secret, cookie="jonsid", root="",
         sid=None, shash=None, secure=0, domain=None, create=True)

req: cgi.Request instance
secret: string
cookie: string
root: string
sid: string
shash: string
secure: true or false value
domain: string
create: true or false value

This method may be overridden by subclasses. It creates a new Session instance. secret is a secret key (i.e. any arbitrary string that you do not disclose) which is used for keying the hash used to verify session identifiers (see _make_hash). This value should be unique for each web site, unless you are deliberately trying to share session identifiers between sites.

cookie is the name of the session cookie which is used to store the session identifier. There is usually no need to change this from the default of jonsid. If secure is true then the 'secure' flag of the cookie will be set, which tells browsers not to send the cookie if the connection is not encrypted. If domain is set then this will be used as the 'domain' parameter for the cookie. root is used as the 'path' parameter for the cookie, with a / appended.

If you wish to identify the session in some other way than cookies, you can set cookie to None and then pass in the session identifier in sid. You may optionally also pass in the identifier hash in shash - if you do then the session identifier will be ignored and a new session created if the hash does not match the identifier. If you omit the shash parameter then the identifier will be assumed correct.

After initialisation has completed, the session dictionary contains the session identifier under key id, the identifier hash under key hash, and if the session was not new, any stored information from previous requests.

If create is false then the session will not be created if an existing session cannot be found. In this case, the session identifier in key id will be None. A new session may then be manually created by calling the create method.

create(self)

This method creates a new session. If the cookie parameter to __init__ was not None then a Set-Cookie header will be created.

save(self)

This method may be overridden by subclasses. It stores the information from the current session's dictionary so that it may be retrieved in later requests. The default implementation does nothing.

Public Static Methods

tidy()

This method may be overridden by subclasses. It is used to delete session information that has expired, and should therefore be called periodically, perhaps from a cron job. Subclass versions of this method may require different parameters to the function - you cannot call this method without knowing the particulars of the particular subclass being used. The default implementation does nothing.

Protected Instance Variables

_req

The cgi.Request instance passed to the session's __init__ method.

Protected Methods

_make_hash(self, sid, secret)

sid: string
secret: string
Returns: string

This method may be overridden by subclasses. It returns the 8-character hexadecimal string which is a keyed hash of the session identifier sid and the secret key secret. The default implementation uses HMAC-SHA, and should not usually need to be overridden.

_create(self, secret)

secret: string

This method may be overridden by subclasses. It creates a new unique 8-character hexadecimal session identifier and initialises it in whatever storage system is being used. self["id"] should be set to the session identifier. Optionally, self["hash"] may also be set to the identifier hash. If the hash is not set then _make_hash will be called subsequently to determine it. The default implementation simply sets self["id"] to a random identifier.

_load(self)

This method may be overridden by subclasses. It updates the session's dictionary with whatever information the storage system has recorded about the session with identifier self["id"]. It should return 1 if the session identifier was located in the storage system, or 0 if it was not (in which case a new session will be created). The default implementation simply returns 1.

Note that this method should only return 0 if the session information could not be located because it did not exist. If any other error occurs (e.g. an I/O error while searching for the session), then an exception should be raised as usual.

class: FileSession(Session)

The FileSession class is a subclass of Session that uses the filesystem to store session data.

Public Methods

__init__(self, req, secret, basedir=None, **kwargs)

req: cgi.Request instance
secret: string
basedir: string

Creates a new FileSession instance. Session data will be stored using individual files in the filesystem, under the basedir directory. If basedir is not specified then the environment variable TMPDIR is used instead, or if there is no such environment variable then /tmp is used. A directory is created under this named jon-sessions-%d where %d is the current user id. If this directory already exists then it must be owned by the current user. req, secret, and kwargs are passed to the base class's __init__ method.

save(self)

The session's dictionary is written to the filesystem.

Public Static Methods

tidy(max_idle=0, max_age=0, basedir=None)

max_idle: integer
max_age: integer
basedir: string

Deletes session files that have expired. If max_idle is non-zero then it is the maximum number of seconds old a file's modification time may be before it is deleted. If max_age is non-zero then it is the maximum number of seconds old a session may be (since it was created) before it is deleted.

Protected Methods

_create(self, secret)

secret: string

Creates the session identifier and its associated file.

_load(self)

Updates the session's dictionary with the stored information from the session's file. Returns 0 if the file did not exist, otherwise 1.

class: GenericSQLSession(Session)

The GenericSQLSession class is a subclass of Session that uses an SQL database to store session data.

Public Methods

__init__(self, req, secret, dbc, table="sessions", **kwargs)

req: cgi.Request instance
secret: string
dbc: Python DB API Cursor instance
table: string

Creates a new GenericSQLSession instance. Session data will be stored using rows in an SQL table. The database is accessed via the Cursor instance dbc and the table name table. req, secret, and kwargs are passed to the base class's __init__ method.

The table must have at least the following fields:

CREATE TABLE sessions (
  ID          CHAR(8) NOT NULL,
  hash        CHAR(8) NOT NULL,
  data        BLOB NOT NULL,
  created     INT NOT NULL,
  updated     INT NOT NULL,
  PRIMARY KEY (ID)
);

This class has only been tested with MySQL, although the intention is that it should work with any DB API database.

save(self)

The session's dictionary is written to the database.

Public Static Methods

tidy(dbc, table="sessions", max_idle=0, max_age=0)

dbc: Python DB API Cursor instance
table: string
max_idle: integer
max_age: integer

Deletes session rows that have expired. If max_idle is non-zero then it is the maximum number of seconds old a session's updated time may be before it is deleted. If max_age is non-zero then it is the maximum number of seconds old a session's created time may be before it is deleted.

Protected Methods

_create(self, secret)

secret: string

Creates the session identifier and its associated table row.

_load(self)

Updates the session's dictionary with the stored information from the session's database row. Returns 0 if the row was not found, otherwise 1.

$Id$