[mod_python] The right way to handle sessions

Amir Salihefendic amix at amix.dk
Fri Aug 13 18:32:28 EDT 2004


> def createSession(req):
>     new_session = Session.Session(req)
>     new_session.unlock()
>
>     #Check id
>     req.write(new_session.id())
>
>     return getSameSession(req, new_session.id())
>
> def getSameSession(req, SID):
>     same_session = Session.Session(req, SID)
>
>     #Check id
>     req.write("\n%s\n" % same_session.id())
>
>     return "Done"

Argh forgot something very important (to save the damn session)!:
def createSession(req):
     new_session = Session.Session(req)
     new_session.save()
     new_session.unlock()

     #Check id
     req.write(new_session.id())

     return getSameSession(req, new_session.id())

def getSameSession(req, SID):
     same_session = Session.Session(req, SID)
     same_session.load()

     #Check id
     req.write("\n%s\n" % same_session.id())

     return "Done"

*Tsk tsk*

Med venlig hilsen / Kind regards
Amir Salihefendic
-----
What we do in life echoes in eternity
Den 13/8-2004, kl. 13.30, skrev Amir Salihefendic:

> Thanks a lot for your time spent on the reply, I appreciate it.
>
> "Under what circumstances do you call createSession() instead of 
> getSameSession()?"
>
> Let's take another example:
> I am making a blog-system where I need to have an admin section. I am 
> using the publisher handler.
> Simple forms post username and password to admin.py
> Admin.py has an index function, which has username and password as 
> input.
> In the index function I check if the username and password match, if 
> they do I create an session and store username and password.
> Now, I need to redirect to a new function viewPosts (it's also located 
> in the admin module).
>
> In viewPosts I have to check if the right session is set - else 
> somebody could do admin.py/viewPosts and get access to the admin 
> section.
>
> Of course, I could solve problem in many other ways:
> - Send the SID to viewPosts
> - Place everything in one function (i.e. place everything in 
> admin.py/index)
> - "Append" the session to the req object
> - Make viewPosts private (i.e. do _viewPosts) and then I can only 
> access it by going through admin.py/index
> -etc.
>
> Anyway, I am interested in knowing: What is the smartest way to 
> "share"/access same session across functions (i.e. when you are 
> internal "redirecting")? Example of what I mean by "redirecting" (not 
> working...):
> def createSession(req):
>     new_session = Session.Session(req)
>     return getSameSession(req)
>
> def getSameSession(req):
>     same_session = Session.Session(req)
>     return same_session.id()
>
>
> My guess is to send the SID (working). This seems to be a very light 
> and easy approach:
> def createSession(req):
>     new_session = Session.Session(req)
>     new_session.unlock()
>
>     #Check id
>     req.write(new_session.id())
>
>     return getSameSession(req, new_session.id())
>
> def getSameSession(req, SID):
>     same_session = Session.Session(req, SID)
>
>     #Check id
>     req.write("\n%s\n" % same_session.id())
>
>     return "Done"
>
> (This is a solution I use now.) Of course this is very simplified 
> example...
>
> Med venlig hilsen / Kind regards
> Amir Salihefendic
> -----
> What we do in life echoes in eternity
> Den 13/8-2004, kl. 1.17, skrev Byron Ellacott:
>
>> Amir Salihefendic wrote:
>>> I welcome myself to this list ;-)
>>
>> Welcome!
>>
>> [working example]
>>> def createSession(req):
>>> def getSameSession(req):
>>
>> The important thing to note here is that the code is identical in 
>> both calls.  That is, if you call Session.Session(req) with no 
>> session ID in cookies, or the existing session ID has no matching 
>> session stored on disk, a new session ID is generated.
>>
>> But, the session is /not/ written to disk.
>>
>>> def createSession(req):
>>>     return getSameSession(req)
>>> def getSameSession(req):
>>>     return same_session.id()
>>
>> So when you change to calling getSameSession() from createSession() 
>> you are in fact creating /two/ sessions.  My guess would be that your 
>> apparent infinite loop is in fact a deadlock, caused by the fact that 
>> your second created session will be reusing the session ID created by 
>> the first one, and then attempting to establish a global lock on that 
>> session ID.  Bad.
>>
>>> This does not work - it makes an infinitive loop..!  Now to fix this 
>>> you need to unlock the session in createSession (.. I have no clue 
>>> why you have to do this..?). And then you need to restart apache...  
>>> i.e.:
>>
>> This bears up my analysis well.  The locking done by the Session 
>> module is an Apache-wide lock on the session ID.  So, when 
>> createSession() first creates a session, it locks that sid.  Then, it 
>> calls getSameSession() which attempts to lock the same sid.  The lock 
>> call blocks here, waiting for the first lock to be released, but that 
>> release will never come.  If you cause the first created session to 
>> unlock itself, you will not create a deadlock, but you will need to 
>> restart apache to break an existing deadlock.
>>
>>> But this does not work quite well.. If you delete the Session:
>>> And then you do this:
>>> First time the id's aren't same - after that they are the same.
>>
>> When a session has been deleted, it is marked as invalid and calling 
>> .load() on that sid will fail.  .__init__() will create a new sid if 
>> .load() fails for an existing one, so I suspect you are seeing this 
>> behaviour.
>>
>> Overall, it seems you are making the session management process far 
>> more complicated than it needs to be.  Under what circumstances do 
>> you call createSession() instead of getSameSession() ?
>>
>> I am successfully using the Session module to handle an HTML forms 
>> based login system:
>>
>> session = Session.Session(req)
>> if NeedAuth and not session.has_key('username'):
>>     redirect(AuthPage)
>> ServePage(req)
>> session.save()
>> return apache.OK
>>
>> This is a simplification, since I use an extensible application 
>> object that allows you to change how sessions are generated and how 
>> users are authenticated, but it boils down to the above.  I create a 
>> new session or get an existing session.  I do not care which.  If the 
>> page being requested needs auth, but the session doesn't contain a 
>> username key, I redirect[1] to the login page, which stores the 
>> username value into the session if the user presents the right 
>> credentials.  Otherwise, I serve the requested page, then save the 
>> session, and Bob's a builder.
>>
>> Note that I cannot distinguish between an expired session and no 
>> session at all, but this is a limitation of the Session module.  I 
>> can distinguish between a new session and an existing session by 
>> calling session.is_new(), but that distinction turns out not to be 
>> very important.
>>
>> At some point, I will need to extract the sid from the cookie set 
>> myself, to be able to distinguish between a timed out session, an 
>> invalidated session, a missing session and a brand new session.  (Or 
>> else I'll have to patch the Session module, which I'm not real keen 
>> to do.)
>>
>> -- 
>> bje
>>
>> [1] The 'redirects' I do are simply changing what view my code 
>> believes it is processing, so execution continues down the line, and 
>> session.save() is called in due order.  If you're using an Apache 
>> internal redirect or a 302/303 redirect, you should ensure new 
>> sessions are saved as soon as created with "if session.is_new(): 
>> session.save()".
>> _______________________________________________
>> Mod_python mailing list
>> Mod_python at modpython.org
>> http://mailman.modpython.org/mailman/listinfo/mod_python
>>
>
> _______________________________________________
> Mod_python mailing list
> Mod_python at modpython.org
> http://mailman.modpython.org/mailman/listinfo/mod_python
>



More information about the Mod_python mailing list