Persistent sessions
peter
p2.edoc at gmail.com
Fri Feb 14 18:14:47 UTC 2014
At 8:59 AM -0800 14/2/14, Ron Garret wrote:
>On Feb 14, 2014, at 2:31 AM, peter <p2.edoc at gmail.com> wrote:
>
>> I find that I have the same requirement and would like not to
>> re-invent wheels so would much appreciate hearing any insights you
>> gained rg.
>
>Turns out to be very easy. HT sessions can be accessed and set via
>the generic function ht:session-db, which returns an alist. The
>alist keys are fixnums and the values are opaque HT::SESSION
>objects. To make a persistent session all you have to do is
>serialize and restore this alist. All of the slots of an
>HT::SESSION are atoms, except for HT::SESSION-DATA, which is an
>alist, but it contains only values that you put there. So
>serializing an HT::SESSION is not hard.
>
>The challenging part for me turned out to be restoring Hunchentoot's
>internal session state on restart, because HT assumes that there is
>an active request whenever a session is created:
>
>? (make-instance 'ht::session)
>> Error: Unbound variable: *REQUEST*
>
>So you have to restore sessions using ALLOCATE-INSTANCE instead of
>MAKE-INSTANCE. Other than that it is completely straightforward.
>(I ended up writing a little general-purpose object serializer using
>the MOP.)
>
>> For local hosting, I used a persistent global session-ID counter as a
>> patch (ensuring session-IDs can't overlap, but that's not acceptable
>> for cloud hosting.
>> All I need really is persistence of the client's cookie validity, as
>> all state data I keep outside HT.
>
>Not sure I understand this. HT natively provides unique (per
>server) session id's. If you want to make session id's unique
>across multiple servers that is a different problem than making
>sessions persistent. But HT already has a hook for that: the
>generic function NEXT-SESSION-ID. Is there a reason that doesn't
>work for you?
We're taking different approaches. Here I am obliged not to make
anything persistent in the hunchentoot server file system. So the
challenge is to make the cookie itself the only thing that is
persistent (so stored in the browser).
My vague plan is:
- ignore the session-ID, use just the cookie-value
(as in "0AD9630B5FEA2AEC6E3C24F493B1C0C1")
- bypass session-too-old-p for now
(later transport the session start time externally to the cookie-value)
- so the sequence goes thus:
- incoming url from new client (no cookie)
HT makes new session and cookie, and sends cookie back to client
- subsequence incoming requests carry a cookie, so handled as usual
- re-boot HT (session DB data lost)
- original client access (carried cookie)
HT has to make a substitute session to serve this client
hence ignore the session ID throughout, and search the session DB
using the cookie value, as in:
(defun get-stored-session (cookie-value)
(cdr (assoc cookie-value (session-db *acceptor*) :test #'string=
:key 'session-string)))
Now I'll have to promulgate the consequences of this shift from
managing session by ID to cookie-value.
But I'm worried that I've overlooked something. Why wasn't this
approach (indexing session by cookie-value instead of session-ID do
in the first place). I.e. I fear there must be a good reason what
session-IDs were used. Unless there was a need to prevent session
persistence.
I am cowering in anticipation of receiving a castigation for missing
the most obvious thing. But persistent session without using any
local file store is my requirement.
peter
More information about the Tbnl-devel
mailing list