[mod_python] The right way to handle sessions

Amir Salihefendic amix at amix.dk
Fri Aug 13 14:30:23 EDT 2004


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
>



More information about the Mod_python mailing list