Session Management gives the developer a tool for maintaining state or caching useful data across different page requests. It is an optional feature of ExSite Webware.
ExSite stores constants and shareable data in one of three locations (all exported by ExSite::Config):
Because HTTP is a stateless protocol, you normally only get access to the constants in %config and the current state in %share. If you want to maintain state across different page requests, you need a mechanism to save data following one request, and restore that data on the next request from the same user. This is the purpose of session managment, and in ExSite, the %session hash is used to hold this session data.
Session data are simple key=>value pairs that are stored in the %session hash that is defined and exported by ExSite::Config. This hash works much like the %config and %share hashes, except that it is not good at storing complex data structures (ie. it's best to use only scalars in the value).
Examples:
If your installation has not been configured to use sessions, then the %session hash will be empty on each page request, and will function something like %share as a result.
If your installation has been configured to use sessions, then the %session hash will automatically remember data placed into it for a certain period of time. By default, this time is 24 hours under continuous use, or up to one hour of idle time, whichever comes first. After this time, the session data is cleared. The remembered session data is for that particular user only. Other users maintain their own %session hashes.
No special effort is required to initiate a session; ExSite will automatically set up the user's session as soon as it's needed (typically on the first view of a dynamic page). When programming, simply write to or read from the %session hash as needed. You can overwrite older session values, and delete session keys, as necessary. ExSite takes care of preserving that data for future requests.
ExSite stores the user's session ID in a cookie; the user must accept this cookie for session management to work. (Otherwise ExSite will initiate a new session each time session data is needed.)
If you are using sessions, it can be a small performance enhancement to move your system authentication logic over to the session model. This reduces database lookups when authenticating users, and will improve system performance. To use session-based authentication, use the following exsite.conf configuration parameter:
auth.type = session
When this happens, ExSite will store the user's authentication information in the session data, so that it does not have to be looked up on each page view. Since the session is cleared after 1 hour of idle time, or 24 hours of continuous use (by default), the user's login identity will disappear after that time, and they will effectively be logged out. In some cases, this can be a disadvantage to using session-based authentication, since some users may prefer to leave themselves logged-in for days or weeks.
If there are database lookups that have to be performed on all or most page views, it makes sense to store the relevant data values in the session data to ease the database load and improve performance.
Sessions are only good at storing simple values, so it's easier to store and look up particlar database columns, than whole records. However, you could always URL-escape a datahash, and store that as a simple string value in the session data, if needed.
In some cases, ExSite needs to perform searches for particular records. Sometimes the searches are simple fetch_match()-style queries, and sometimes they are recursive searches through chains of linked records. In either case, you can improve performance by simply recording the ID of the sought record in the session data once it has been found. You still have to look up the record on each page view, but you save yourself the more expensive task of performing the search each time.
Since session management is optional under ExSite, an application cannot necessarily expect that session management services will be available. Ideally it should be coded to utilize session data that is available, but do the work of obtaining that data, if not. For example:
# get $foo from session, or load $foo into session $foo = $session{foo} || ( $session{foo} = &get_foo() ); # slightly more robust version that allows for null or undefined $foo $foo = exists $session{foo} ? $session{foo} : ( $session{foo} = &get_foo() );
There is no harm in loading session data into %session if session management is not enabled. The data simply won't be preserved to the next request, but is still perfectly useable on the current request.
Two config settings control how sessions are expired:
# maximum lifetime (in minutes) of a session - 24 hrs session.max_lifetime = 1440 # maximum idle time (time between requests) - 1 hour session.max_idle = 60
The default times are shown, but you can change these in exsite.conf.
Expired sessions are cleaned out by a garbage collector that runs every time a session is (re-)opened, and before that session is validated. (That means that an old session could still have its data in the session file when the user connects, but the garbage collector will run before that data is returned to the user. If the garbage collector removes the old data, the user will receive nothing.)
Session data is kept in a DBM file that stores encoded strings indexed by the session ID. The session ID is a unique string, typically an MD5-hex hash of the requester's IP, the current system time, and a random number. The session data is an URL-encoded sequence of simple key=>value pairs, for example:
dff685ab49abc2074ad88080a48087fe => _atime=1121455479&_ctime=1121455412&uid=456&mydata=xyz
Or, in decoded form:
SessionID "dff685ab49abc2074ad88080a48087fe" _atime = 1121455479 _ctime = 1121455412 uid = 456 mydata = xyz
Every session automatically includes the _atime and _ctime values, which are the last-access time, and creation time of the session, respectively (Unix system times).
Note that the %session hash is tied to the URL-encoded data under a particular session key, and not to the overall DBM file. More details are available in the ExSite::Session.pm source file.
Because session data is URL-encoded inside the session file, it can normally only hold scalar data values, and not data structures. However, with a little care, you can encode your data structures so that they can be stored in a session variable. Here is a method for encoding and storing a hash inside a session variable:
use ExSite::Misc; # ENCODE my %datahash = ( ... ); my $data = &EncodeHash(%datahash); $session{data} = $data; # DECODE my $data = $session{data}; $data =~ s/%(..)/pack("c",hex($1))/ge; my %datahash = &DecodeString($data);
ExSite uses the following files for managing session data:
The file names may be reconfigured using the config parameters session.file and session.lockfile. Both files must have permission mode 666 to work properly.
The following shell commands will create the session files appropriately:
% perl -e 'dbmopen(%s,"exsite.session",00666)' % touch exsite.session.lock % chmod 666 exsite.session*
Once these files are created, the following config parameter in exsite.conf will enable session management:
session.on = 1