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.
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()
The base class for all exceptions defined by the session
module.
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.
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).
__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.
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.
_req
The cgi.Request
instance passed
to the session's __init__
method.
_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.
The FileSession
class is a subclass of
Session
that uses the filesystem to store
session data.
__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.
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.
_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
.
The GenericSQLSession
class is a subclass of
Session
that uses an SQL database to store
session data.
__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.
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.
_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: session.html,v 0416d65875b7 2014/03/05 17:37:06 jon $