On Thu, May 10, 2001 at 11:00:39PM -0500, Joel Gwynn wrote:
> Can anyone point me to some simple resources on
> understanding/implementing state machines in Perl/SQL?
>
> I'm working on an ecommerce site and getting sick of all the standard
> kludgy redundant code for maintaining state, session ID's etc. I keep
> hearing that there are these things called "state machines" which will
> auto-magically track all these variables.
>
> I need a fairly elementary primer with LOTS of examples.
As others have mentioned, you don't need a state machine in the classic CS
sense, but you may benefit from a mechanism to maintain sessions and their
associated state. This is more of an application framework than a state
machine, though it has some features of a state machine.
I gave a talk on this some time ago at one of the technical meetings.
What I implemented is similar to CGI::Session, which
you'll find on CPAN, but with some additional features and some differences.
I have seen some of these issues mentioned in various places, but not all at
the same time. One of these days, I'll sit down and fill that void. In the
mean time, here are some thoughts you might find useful.
The basic idea is that you assign sessions to every new http connection and
maintain any state information you need on the server side which propagating
the session id through every page the client visits. I use a
database table to store the session data. If you only have a single machine, you have
more
options about where and how to store the data. If you have multiple, load balanced
servers, you pretty much have to keep the data in a shared database since a
client could connect to any one of your web servers. The three biggest
issues that came up when designing this were security, persistence, and storage
format.
Security:
You want session id's to be breakable only with great difficulty. My
session-id's consist of an md5 hash of a secret string and the environment
(as a long string),the length of the environment string, and the current time;
a random string (mod_unique is great for this), and the value of the primary key of the
session (from the database). The first two are of known length, so the last
one could be (and in fact is) of variable length. When the client sends a session id,
it is checked against the table to be sure all these values still match up.
Since the security of the user session depends on this ID, it must be secure.
An attacker may be able to guess some of the values, but would have a hard time
guessing
all of them. This is obviously predicated on the security of the rest of the
system including the non-web related parts. Mismatches are obviously logged.
A typical session id could be:
/S=708c29ade99f1b6a43f098b10c7b05f3Ov0xeozvpSQAAGVIPl4101987/
Which embedded in the URL, but stripped out and placed in the environment
with mod_rewrite before the script is called. The session id is ugly but
useful. You could check to see if the client has cookies turned on and
transparently put the ID in a cookie instead. CGI::Session's ids are much
simpler and also less secure. Yes, there is more of a performance hit with
string manipulations and the database lookups on every hit. That is part of
the cost of security.
Persistence:
Once you have a session, you have to make sure that all links to other
pages on your site have the session id. This essentially means you have to
either generate them in your scripts or use templates. I use templates since
I work with other people who are more responsible for UI issues.
Storage:
To make the interface as simple as possible for scripts, the Session
module stores and returns scalars. Obviously this is not much of a
limitation: I am just forcing scripts to use references when they need to
store arrays and hashes. The database, OTOH, does not understand
scalars. So I use the Storable module to convert the scalars into binary
strings and MIME::Base64 to encode them for storage in the table. The
reverse combination restores them back to scalars. CGI::Session does this too.
With this, you can do cool stuff like trapping for user access to a page
that requires them to log in and redirecting the browser to the login page,
which, after a successful login, redirects back to the original page.
This is probably more than you wanted, but it is, occasionally, worth
talking about.
-Gyepi
--
Every great mistake has a halfway moment, a split second when it can
recalled and perhaps remedied. --Pearl S. Buck