![]() |
State-less SessionIsn't that an oxymoron? |
There are many tool-kits that make it easy to embed an application in a frame-work that offers a web-interface, and creates the equivalent of the concept of a "session" that is still well-known from the days of simple terminals.
Without such tool-kits, a web-interface would offer
a "state-less" sequence of events, where each
interaction between the end-user and the application is
treated as an isolated event, with no knowledge of
prior activities that the same end-user would have
completed.
For many applications, a certain amount of recollection
of prior events is desirable, if not essential, hence
the desire for "web-sessions".
In those cases where the popular tool-kits cannot be used, it is important to remember that it doesn't take too much to create the equivalent of a "session" in an environment that is basically "state-less".
The idea of a stateless session uses the feature that each interaction between an end-user and a web-server can present a number of variables, each with their own value. When a session is established, the web-server will present a special variable to the browser (the name of this variable can be implementation-specific) with a value that uniquely identifies the session, and when the end-user communicates back to the server, this variable is included in the data-stream, so that the server can recognize the interaction as part of a session that it knows about.
Note that, as opposed to "cookies", which are stored on the computer where the browser is running, the information about the session will be stored on the server, and only a "token" that identifies the session will be exchanged between the server and the browser.
The management of a state-less session would work like this:
The initial call to an application would use a URL (Universal Resource Locator) that could look like: http://site.company.com/Application.
Whenever the program for this application is
invoked, it will check the values of its parameter
variables.
There should be one, let's call it SessionToken
for the purpose of this discussion, that would have a
value that could implement the concept of a
session.
When the above URL is processed, no values for
variables are included, and the receiving application
will not be able to find a value for its
SessionToken. Once the application becomes aware
of this, it knows to start a new session. If there is
no need for secured access or user-registration, a
session token can be generated immediately and the
application can start with its first page.
If there is a need to keep track of who is using the
application, the software
can transmit a login form, which would
request that the end-user provide a valid
identification.
Typical variables to include in such a form are
(their names could be anything,
let's assume the following names for the purpose
of this discussion):
If there is any problem, the login form can be presented again (with all the same initial values), and some indication that "access was denied". The message should not contain information that would allow a hacker to figure out exactly which part of the transmitted information was invalid.
If all information from the login form is acceptable, the first page of the application can be displayed. The form and content of this page is completely up to the application. Calls to next pages, sub-parts or phases in the application could be implemented through hypertext links (URLs) or through forms with buttons. In either case, the application would be called at the same starting point, however, there would be a number of variables that would, at that stage, have a different value. Most of these variables would be completely application specific: these are the variables that the application needs to do its work.
There should be just one additional variable, SessionToken in this example, that always must be present (after all, if it would not be present, the program would present the login form or go back to the first page of the application...). The value of this variable, however, is also is application dependent. It could be a value as simple as 0 or 1 (1 = currently logged in), or it could be a multi-part value that contains information about the sub-parts of the application that are currently accessible and that is transmitted in an encrypted fashion.
If security is an issue, the value of the token should be complex enough that a hacker would not be able to guess (or worse: predict) its value.
That's the idea...
A session, of course, can last as long as the application is willing to allow it it last, but, in general, it does make sense to give each session a finite life-span. After all, in the days of traditional terminal sessions, it was already hard to motivate end-users to "log-off" when they were done with their tasks, and in the days of web-communication, the end-user might not even notice that there is an option to terminate an open session, and just move to the next activity by clicking on a "bookmark" in a menu of favorite web-addresses...
A simple method of setting an expiration time for a
session can be implemented at the point where the
application checks the value of its
SessionToken. The application could store an
expiration time for each token, and, when a token is
presented, move to the initial page (or login form)
when the token has expired.
In most of my applications, I initially set the expiration time
to 5 minutes after login, and then extend the
expiration time each time a subsequent interaction
takes place to become 15 minutes after that
interaction.
Set token=$Get(%KEY("SessionToken")) Do:token'="" . New exp . Set exp=$Get(^jsrToken(token)) . If 'exp Set token="" Quit ; This token not recognized... . If exp<$$Now() Set token="" Quit . ; Extend expiration of token by 15 minutes . Set ^jsrToken(token)=15*60+$$Now() . Quit ... Now() New h Set h=$Horolog Quit $Piece(h,",",1)*86400+$Piece(h,",",2) |
Basically, the level of desirability is often dictated by the application, and sometimes up to the whim of the programmer.
Let's use an
implementation of the game of Hangman as an
illustration. In this game, the end-user has to guess a
word, and performs guesses by supplying characters. The
opponent (in this case the application) will check the
characters supplied by the end-user and for each wrong
character add an element to a drawing. When the drawing
is complete, it will show a person hanging from a
gallows, and the player has lost the game. If the
player fills in all characters of the word
before the drawing is complete, the player
wins.
Obviously, the application would need a way of remembering which letters have been guessed, and how many erroneous characters have been guessed.
One
possible implementation would be to pass this
information in variables each time the display is
updated (from server to browser), and each time the
end-user makes a new guess (from browser to server).
(Click here to download the M[UMPS]-program.)
Another
possible implementation would be to maintain
this information on the server, and update it after
each interaction with the end-user.
(Click here to download the M[UMPS]-program.)
Set ^jsrHang("Session",token,"Stage")=CurSt Set ^jsrHang("Session",token,"Guessed",letter)="" |
In the former implementation, it will be possible for the end-user to use the "back" button on the browser to go back to the page of a previous step in the game, whereas, in the latter implementation, the application could detect that the end-user reverted to an earlier stage in the game, and proclaim a loss by default for cheating, or just continue the game, keeping in mind all activity that has occurred between the transmission of the page that is now the "current" one, and the one that was actually transmitted most recently.
Which of these two types of implementation is to be preferred, of course, is often up to the implementor of the application. In many applications (especially those where money moves between different owners) a situation where one can revert to an earlier stage is simply not acceptable; for other applications it might actually be very desirable to be able to "back up and try again"...
Ed de Moel is past chairman of the MDC and works
with Jacquard
Systems Research.
His experience includes
developing software for research in medicine and
physics.
Over the past ten years, Ed's has mostly focused on the
production of tools for data management and analysis,
and tools for the support of day-to-day operation of
medical systems.
Ed has worked with the Greystone Group at Sanchez
on a project to make GT.M more compliant with the 1995
ANSI standard, and currently works with the Department of Veterans
Affairs on their project to add images to the medical
record. Ed can be reached by
e-mail.