This section explains in some more detail how the builtin session management system works.
Each session in the system has an associated session identifier, or session
id for short. This session id is a 21 character string of the form
ddd-dddddddd-dddddddd
where all the d
characters are decimal
numbers. The last two parts each contain a 26 bit random number, while the
first part contains a simple checksum. The random numbers are extracted from
a strong random source so the system should be safe from session identifier
guessing methods.
The session id is used to uniquely identify the session. All session related
information and all session variables are stored in a database indexed by
the session id. To keep track of a session, the session id must be passed on
from one http request to the other in the same browser session. This is done
in two ways. First, the session id is put in an http cookie. Second, because
not all user agents support cookies, the session id is added to all relative
URLs inside the draco system, as the last part of the path
component6.1. For example, an url that would normally be:
http://www.test.org/hello.dsp?greet=test
, becomes
http://www.test.org/hello.dsp/xxx-xxxxxxxx-xxxxxxxx?greet=test
when
the session id is added. This is all done transparently for <a>
and
<form>
tags using the tag rewriting mechanism.
When both the cookie and the URL contain a session id, the one from the URL
has precedence. If a request is made, and there is no session id in a cookie
or the URL, a new session is generated if the remote client is not
recognized as a web robot. A new session is by default not persistent and
not logged in. A session can be made logged in using session.login()
.
When a session is logged in, a so-called authentication token cookie
is set. This cookie contains large (currently 64 bit) random number that
acts as a shared secret between the web application and the client. This
requires that clients support cookies if they wish to log in. Draco uses
this authentication token for authentication instead of the session id
because the session id can ``leak'' outside via referrer logs and because it
is visible in the address bar of the browser. The authentication token needs
to remain secret. If somebody can access the authentication token for a
session, they can take it over. If you want to be very secure, you must
always use an encrypted connection for logged in sessions. Furthermore, if
you notice that a client with a logged in session session is requesting a
page through a cleartext channel, the authentication cookie is already
compromised. The session should be logged out immediately so that the
authentication token looses its significance. This check can be easily
performed in a requestStart()
event. The procedure is illustrated in
the code fragment from __event__.py below:
from draco.event import Event from draco.session import session from draco.server import server class MyEvent(Event): def requestStart(self): if session.userid() and server.port() != 443: session.logout()
Note that port 443 is the standard port for encrypted communications (https). Also note that this is only required if you want strong security. This is the reason it is not default behaviour in Draco.
Logged in sessions can additionally be made persistent. Persistent sessions have a large timeout and are kept between different browser sessions by making the session id and the authentication token cookie persistent.
Old sessions are expired every hour through the special ExpireSessions system task registered to the event scheduling service.