My concern is synchronization issues when relying on server-side
session data too much. It's quite easy to drop a variable in session
to use in the next request. A user hits the browser back button and
things are left in an inconsistent state.
That's session-store independent, though. You'll get precisely the same
behaviour if you store the inappropriate data in a cookie.
Sessions already use a cookie, so for many applications it makes sense
to pop the essentials (user id) into a cookie and otherwise architect
without sessions. Flash remains useful for non-Ajax requests, so
using the CookieStore for that could be a plus.
Using the cookie store for the flash certainly seems like a win to me -- if
the user plays silly buggers with the values in there, at worst they're only
going to hurt themselves. No need to waste disk space or database CPU
storing and retrieving that stuff all the time.
On the other hand, though, storing things like user ID in the cookie store
is pointless. All you're doing then is using the ActiveRecordStore but with
a different key to retrieve stuff (user ID instead of session ID). If you
store multiple IDs in there (user ID and cart ID, for instance) then your
performance will likely be worse, because you're hitting the database
multiple times to retrieve both of them, rather than just the one chunk of
session data.
You can't possibly get away with *not* loading the models identified by the
IDs in the cookie, even if you only need the ID, because you can't possibly
trust the information that the user is providing -- mangling the user ID to
log in as someone else (if the hash is easily breakable), or even just your
basic common-or-garden-variety replay attack (nonces have the same
server-side storage problem as the data itself, and timestamps give an
easily readable window, while encryption just leaves the attacker to guess
how long the window is, it doesn't close the window). So you need to
validate the ID(s) the user is providing before relying on it/them.
At least with a server-side session store (of whatever variety) session keys
are large enough that guessing them isn't feasible (whereas most everyone
still seems to use sequential integers for user IDs, rather than UUIDs), and
you as the system operator can invalidate a session key just by clearing the
associated data. Once you give data to the client, you lose that much
control of it.
I suppose you might get some performance benefits if you store IDs in the
cookie that are only needed on very few pages, so you don't have to validate
it very often. I'm not guessing that there are many webapps out there that
could benefit from that particular brand of optimisation (although the flash
storage could probably benefit a lot of people -- anyone who runs a purely-
or partially-public Rails site that uses the flash on their public pages).
Anyone want to start a pool on how long it'll be before someone
re-implements ActiveRecordStore on top of CookieStore by just storing a
session_id in the cookie and then loading up an arbitrary chunk of data in
the database based on that value? I'll take 3 months.
Actually, that gives me a bit of an idea -- you could prevent session ID
guessing on a server-side store by making the session ID key:hash, where key
is what we have now and hash is {md5,sha1}(key+secret). Then the server can
validate the session ID with no more than the session ID and the secret.
Doesn't stop replays if you don't expire your sessions, but at least slows
down people guessing.
At any rate, I'm not anti-CookieStore, because I just don't care. I've got
my template Rails project with all my customisations and plugins, and if I
have to change another config option or two, that won't be a big deal for
me. Defaults are always going to piss someone off, so I've given up
worrying about them. At any rate, a lot of the tradeoffs in client-side
stores are similar to server-side stores, just in different clothes, so
there isn't such a big win. I suspect that I might use an encrypted
CookieStore on apps that don't have a database behind them, just to save me
a cron job.
If someone's in a wish-granting mood, being able to store the flash in a
cookie (either a separate one, or as part of the session ID one, isn't a big
deal) while storing the session proper in whatever store you've configured
would be wonderful, and that session ID guessing thing isn't patented or
anything (at least not by me <grin>).
More on RESTful state transaction models:
"To achieve a RESTful state transaction model, in a nutshell, means
passing enough data back and forth so that a user can click on any
feature or function of the application, in any order, and the server
will (1) know what to do every time without fail, and (2) will not
'remember' each client's previous states. This implies that the server
is 'stateless' with respect to specific client data. The server has a
state of it's own, and knows it's own transaction state, of course.
But it is only 'aware' of each client's state when it is contacted by
the individual clients, and the client notifies the server of it's
state."
devchix.com at Directnic
I can't manage to read that snippet in any way that isn't either horribly
insecure ("trust what the client is giving you") or is precisely how things
are done now ("client gives me some identifier, I retrieve the current state
of the session from my 'server side state'"). Perhaps the rest (heh) of the
article provides a bit more detail, but reading articles written by RESTful
advocates irritates me for some reason. I like REST, but RESTers bug me.
<grin>
- Matt