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