django.contrib.sessions problems

134 views
Skip to first unread message

mrts

unread,
Apr 3, 2008, 4:36:33 AM4/3/08
to Django developers
SessionStore is missing a clear() or invalidate() method that will
destroy the session. Is this intentional? If so, why? Cleaning a
session is such a common requirement for session frameworks.

Looking through tickets, I found the following relevant to general
session logic (in no particular order):
http://code.djangoproject.com/ticket/5549#comment:5
http://code.djangoproject.com/ticket/2548
http://code.djangoproject.com/ticket/3304
http://code.djangoproject.com/ticket/1180
http://code.djangoproject.com/ticket/6791
http://code.djangoproject.com/ticket/6941

Some of them are interrelated, some of them pose security risks.

Quoting #6941:
[4:17pm] jacobkm: Also, there's the question of whether the session is
tied to the browser or to the user -- we're a bit muddled there
currently.

We shouldn't be muddled on that :) .Perhaps a bit of refactoring needs
to be done on the features and logic of sessions? Beaker (http://
beaker.groovie.org), referenced in #5549, looks like a sound base to
compare Django session backend with (both feature- and logic-wise).

What I personally need is a secure session framework that
* has a well-defined relationship to request.user, preferably being
cleanly separated from it,
* will not be re-used under any circumstances (#6941) and is
protected against key collisions (#1180),
* supports concurrency (uses locking throughout as Beaker does, think
mod_wsgi with threads),
* can be cleared/destoyed,
* supports controlling session lifetime (http://
code.djangoproject.com/ticket/2548#comment:8 describes the use case).

Regards,
Mart Sõmermaa

Mike Axiak

unread,
Apr 3, 2008, 4:48:54 AM4/3/08
to Django developers
On Apr 3, 4:36 am, mrts <m...@mrts.pri.ee> wrote:
> Quoting #6941:
> [4:17pm] jacobkm: Also, there's the question of whether the session is
> tied to the browser or to the user -- we're a bit muddled there
> currently.

Let me reiterate a position that I posted on #6941. After reviewing, I
actually *don't* think we're all that muddled. A session is
{{{request.session}}} and is represented by the browser's session.
Whereas a user is {{{request.user}}} and is completely separate.

That being said, there are many use cases that would require a change
{{{request.user}}} to somehow signal the creation of a new session. I
am not sure how we should represent this this other than either making
it the forced default or having people wrap the login views.

> What I personally need is a secure session framework that
>  * has a well-defined relationship to request.user, preferably being
> cleanly separated from it,
>  * will not be re-used under any circumstances (#6941) and is
> protected against key collisions (#1180),
>  * supports concurrency (uses locking throughout as Beaker does, think
> mod_wsgi with threads),
>  * can be cleared/destoyed,
>  * supports controlling session lifetime (http://
> code.djangoproject.com/ticket/2548#comment:8 describes the use case).

After reading through these, I think most of these can be satisfied
with the proper session backend. Why not write a "secure" session
backend? (You would presumably also need to require signed cookies for
the session.) I would be interested to see what it would look like.

Cheers,
Mike Axiak

mrts

unread,
Apr 3, 2008, 5:23:37 AM4/3/08
to Django developers
> After reading through these, I think most of these can be satisfied
> with the proper session backend. Why not write a "secure" session
> backend? (You would presumably also need to require signed cookies for
> the session.) I would be interested to see what it would look like.

I think a general refactoring is required. Explicit session
destruction and threading should be supported by all backends. Looks
like sessions are the only bit that may pose problems when running
Django under threaded WSGI, quoting Graham Dumpleton from
http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango:

"If any area of Django does give problems it may be its support for
sessions. This is because Django does not implement any form of global
session locking. That this is lacking though should by rights also
cause problems with multi process server configurations as well as
multithreaded servers. It may be the case though that problems may
more readily occur in a multithreaded server, especially in AJAX heavy
applications which execute many concurrent requests which require use
of sessions."

Is this correct or are there any other modules that are not thread-
safe?

Graham Dumpleton

unread,
Apr 3, 2008, 7:35:49 AM4/3/08
to Django developers
On Apr 3, 8:23 pm, mrts <m...@mrts.pri.ee> wrote:
> > After reading through these, I think most of these can be satisfied
> > with the proper session backend. Why not write a "secure" session
> > backend? (You would presumably also need to require signed cookies for
> > the session.) I would be interested to see what it would look like.
>
> I think a general refactoring is required. Explicit session
> destruction and threading should be supported by all backends. Looks
> like sessions are the only bit that may pose problems when running
> Django under threaded WSGI, quoting Graham Dumpleton fromhttp://code.google.com/p/modwsgi/wiki/IntegrationWithDjango:
>
> "If any area of Django does give problems it may be its support for
> sessions. This is because Django does not implement any form of global
> session locking. That this is lacking though should by rights also
> cause problems with multi process server configurations as well as
> multithreaded servers. It may be the case though that problems may
> more readily occur in a multithreaded server, especially in AJAX heavy
> applications which execute many concurrent requests which require use
> of sessions."
>
> Is this correct or are there any other modules that are not thread-
> safe?

For some context of why I came out and said that, read:

http://groups.google.com/group/django-users/browse_frm/thread/a7d42475b66530bd

What I say may not be totally correct, but the comment (which was
correcting my assumption):

"""As can be seen from
the code in django/contrib/sessions/middleware.py and models.py, we
don't do any cross-thread or cross-process locking when creating a
session instance. Maybe we well should be doing something like that
for
people who want to do simultaneous updates -- as might happen in an
AJAX
driven site -- but, right now, we do not. """

was enough for me to at least highlight it as something to watch out
for.

Graham

Collin Grady

unread,
Apr 3, 2008, 1:24:51 PM4/3/08
to django-d...@googlegroups.com
Mike Axiak said the following:

> Let me reiterate a position that I posted on #6941. After reviewing, I
> actually *don't* think we're all that muddled. A session is
> {{{request.session}}} and is represented by the browser's session.
> Whereas a user is {{{request.user}}} and is completely separate.

Except request.user is loaded by using a user id stuffed in session, so they are
definitely tied together right now :)

--
Collin Grady

The reward of a thing well done is to have done it.
-- Emerson

mrts

unread,
Apr 4, 2008, 8:19:18 AM4/4/08
to Django developers
I started http://code.djangoproject.com/wiki/DjangoSpecifications/Contrib/Sessions
to properly sort this out. Please edit.

Jacob Kaplan-Moss

unread,
Apr 4, 2008, 9:00:46 AM4/4/08
to django-d...@googlegroups.com
On Fri, Apr 4, 2008 at 7:19 AM, mrts <mr...@mrts.pri.ee> wrote:
> I started http://code.djangoproject.com/wiki/DjangoSpecifications/Contrib/Sessions
> to properly sort this out. Please edit.

No, please post here. I know you want there to be a formal spec
process, but there isn't. Right now the way we decide things is by
posting them here, and you need to do the same.

Jacob

mrts

unread,
Apr 4, 2008, 9:37:52 AM4/4/08
to Django developers


On Apr 4, 4:00 pm, "Jacob Kaplan-Moss" <jacob.kaplanm...@gmail.com>
wrote:
> No, please post here. I know you want there to be a formal spec
> process, but there isn't. Right now the way we decide things is by
> posting them here, and you need to do the same.

I entirely accept that. The proposal pages are complementary (and,
indeed, secondary) to discussions on the mailing list.

However, I see real value in proposal pages for non-trivial things --
once discussions reach a conclusion, they provide a reference of the
topic that is otherwise scattered around (several) tickets and mailing
list posts. Moreover, both qs-rf and nf-admin have similar
"specification" pages.

So please continue the discussion here *and* edit the page if you
like. Editing is not that important as I will do the final writeup
there in the end anyway, but I'd welcome additions.

But please, Jacob, can you provide feedback on the topic itself as
well?

mrts

unread,
Apr 5, 2008, 2:31:11 PM4/5/08
to Django developers
> Why not write a "secure" session backend? (You would presumably
> also need to require signed cookies for the session.)

The cookies are already signed. Session data +
settings.SECRET_KEY is md5-digested and tampering raises an
exception. So in that sense the sessions are already secure.
Note that it is possible to create controlled collisions for md5,
thus session data *can* actually be tampered with, so I may end
up writing a version based on sha256 HMAC instead someday.
But as of now I can live with md5-based "signing".

Once Python 2.3/4 support will be dropped, we can start using
higher-grade hash algorithms from 2.5 hashlib throughout. But
this is offtopic for current discussion and will not happen in
the foreseeable future.

The relationship between user and session
-----------------------------------------

Associating some session data to logged-in users is a common use
case. That data needs to be deleted once the user logs out.

Currently sessions and users are separated (I haven't checked how
the user is saved in the session, I assume the user is actually
stored in the session under a specific key). This is very good
and should remain so, but doesn't cater for the use-case.

I propose we add a "data bucket" to the user object that can be
used for that purpose.

>>> u = authenticate(username=username, password=password)
>>> type(u.data)
<type 'dict'>
>>> u.data['foo'] = 'bar'
>>> u.save() # pickles the data dictionary and saves it in a text
# field
>>> u.data['foo']
'bar'
>>> logout(request)
>>> u.data
{}

It should be documented that all session data tied to a user
should be saved in that bucket. Sessions may be used for other
purposes or without django.contrib.auth, so they should
definitely remain separate from the user generally.

That would fix #6941.

I'm ready to implement this.

Clearing a session
------------------

Sessions should have a destroy() method that clears the keys and
removes the corresponding session object from the backend store.

>>> from django.contrib.sessions.backends.db import SessionStore
>>> from django.contrib.sessions.models import Session
>>> s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead')
>>> s['foo'] = 'bar'
>>> s['foo']
'bar'
>>> s.save()
>>> dbs = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead')
>>> dbs.foo
'bar'
>>> s.destroy()
>>> s['foo']
Traceback (most recent call last):
...
KeyError: 'foo'
>>> dbs = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead')
Traceback (most recent call last):
...
DoesNotExist: Session matching query does not exist.

After calling s.destroy(), s should be a valid session object that has
a new key.

I'm ready to implement this.

Please comment.

Mike Axiak

unread,
Apr 5, 2008, 5:11:51 PM4/5/08
to Django developers
Hey mrts,
On Apr 5, 2:31 pm, mrts <m...@mrts.pri.ee> wrote:
> The cookies are already signed. Session data +
> settings.SECRET_KEY is md5-digested and tampering raises an
> exception. So in that sense the sessions are already secure.

Sorry, I didn't mean "secure" in the sense that someone can alter the
data. I meant secure in the sense that (a) there is a guarantee of no
collisions and (b) someone else cannot easily hijack the session.

I believe that Graham said was that sessions aren't "threadsafe"
because two sessions could have the same key (although it's very
unlikely). In this way, sessions aren't multi-process or multi-server
safe either. (I would venture to guess the projects that have problem
with this level of concurrency are also the projects that have
multiple servers.)

There was talk long ago of using db-level locking (either through
sequences or transactions) to ensure two sessions cannot create the
same ID. From what I can tell, this was deemed not a good fit for
Django. Since then, the session interface has changed so there is no
need to convince the Django core developers that every Django project
needs these features. You can write your own app that supports this
session key safety and a few other session-based "controversial"
features that are needed for safety. (And if the backend is good, it
might be merged into trunk as a non-default backend.)

Cheers,
Mike

Malcolm Tredinnick

unread,
Apr 5, 2008, 11:17:31 PM4/5/08
to django-d...@googlegroups.com

On Sat, 2008-04-05 at 11:31 -0700, mrts wrote:
[...]

> Once Python 2.3/4 support will be dropped, we can start using
> higher-grade hash algorithms from 2.5 hashlib throughout. But
> this is offtopic for current discussion and will not happen in
> the foreseeable future.

It will be a while beyond that point, too, since you can't just
magically rehash everything with the new algorithms. So you have to be
able to read auth data generated with older algorithms.

> The relationship between user and session
> -----------------------------------------
>
> Associating some session data to logged-in users is a common use
> case. That data needs to be deleted once the user logs out.
>
> Currently sessions and users are separated (I haven't checked how
> the user is saved in the session, I assume the user is actually
> stored in the session under a specific key). This is very good
> and should remain so, but doesn't cater for the use-case.
>
> I propose we add a "data bucket" to the user object that can be
> used for that purpose.

Which would mean a user could only be logged in once each time. :-(

Session objects is the right place to store all session-related data.
It's a many-to-one relation to each user. If you want something that's
one-to-one with a user, that isn't session data and is easy to implement
via your own model, but I'm not sure it's common enough to have a common
API required in Django itself.

You'll need to elaborate more here on use-cases, I think. It might just
be that you haven't explained what you're wanting to do here.

> >>> u = authenticate(username=username, password=password)
> >>> type(u.data)
> <type 'dict'>
> >>> u.data['foo'] = 'bar'
> >>> u.save() # pickles the data dictionary and saves it in a text
> # field
> >>> u.data['foo']
> 'bar'
> >>> logout(request)
> >>> u.data
> {}
>
> It should be documented that all session data tied to a user
> should be saved in that bucket. Sessions may be used for other
> purposes or without django.contrib.auth, so they should
> definitely remain separate from the user generally.
>
> That would fix #6941.
>
> I'm ready to implement this.
>
> Clearing a session
> ------------------
>
> Sessions should have a destroy() method that clears the keys and
> removes the corresponding session object from the backend store.

I don't see the need for an extra method here. Why isn't this just
something logout() would do?

It's easy to destroy a session. Just call delete() on the object (that's
your destroy() method). The root issue is managing the lifetime and I'm
pretty sure that a sessions lifetime ends either when it has expired
(daily-cleanup nukes those things, or whatever equivalent you're using)
or when the user logs out -- thus explicitly ending their session. We
don't do the latter at the moment, but that would seem to be the
straightforward fix here.

Regards,
Malcolm

--
The early bird may get the worm, but the second mouse gets the cheese.
http://www.pointy-stick.com/blog/

mrts

unread,
Apr 6, 2008, 11:21:52 AM4/6/08
to Django developers
> Session objects is the right place to store all session-related data.
> It's a many-to-one relation to each user. If you want something that's
> one-to-one with a user, that isn't session data and is easy to implement
> via your own model, but I'm not sure it's common enough to have a common
> API required in Django itself.

Accepted.

> You'll need to elaborate more here on use-cases, I think. It might just
> be that you haven't explained what you're wanting to do here.

My personal use case:
---------------------

User sessions are used apart from django.auth.models.User. The
application logic doesn't fit well with Django auth (auth
features are not needed and create a minor security risk if an
admin user inadvertently or maliciously enables staff status for an
external
user -- that plainly should not be possible). There is a separate
custom user model for external users (no passwords as user data
is loaded from SSL client certificate). Django auth is used
nevertheless for admin (for internal users). The framework has
it's own login and logout views. During login, minimal data about
the user is loaded from SSL client certificate and stored in
session. During logout, session data needs to be completely
destoyed.

It is paramount that there is a guarantee of no collisions in
session keys, someone else cannot hijack the session and all data
is destroyed after logout.

CSRF middleware is used for protection during form submission
(btw, I have some problems with it, but this is a different
issue).

The use case I had in mind when proposing the "bucket":
-------------------------------------------------------

Think e.g. Amazon-like workflow: I have an anonymous session and
a few books in my shopping basket. Then I login to make the
purchase. I add some sensitive volatile data to my account (I
can't think of an example for this case right now, but you get
the point). Reviewing the hefty sum total I change my mind and
decide not to purchase anything. I log out from my account and
expect that the shopping basket still remains filled with my
selections, but the volatile data associated with my login is
destroyed.

So, there are two types of session data, one type is related to
Django auth user and should be destroyed from the session when
the user logs out. The other type does not require login and
should remain in the session after logout.

As you noted above, the volatile data is easy to implement via
your own model (by attaching a profile to user), so a common API
is not that necessary. But storing free-form key-value pairs looks
useful to me.

> I don't see the need for an extra method here. Why isn't this just
> something logout() would do?

This is something that logout() *might* do. But considering the
case above, I'm rather +0 for adding a destroy_session parameter
to logout() (and login() for that matter) that defaults to False,
or a wrapper, secure_logout()/secure_login().

According to my personal use case, as auth is not used, an
explicit session destruction mechanism is needed, thus
destroy() is required. logout() should use destroy(), not
vice-versa.

> It's easy to destroy a session. Just call delete() on the object (that's
> your destroy() method). The root issue is managing the lifetime and I'm
> pretty sure that a sessions lifetime ends either when it has expired
> (daily-cleanup nukes those things, or whatever equivalent you're using)
> or when the user logs out -- thus explicitly ending their session. We
> don't do the latter at the moment, but that would seem to be the
> straightforward fix here.

Delete is not documented in
http://www.djangoproject.com/documentation/sessions/#using-sessions-in-views
It requires the session key as parameter, so it is cumbersome to
use.

Standard dictionary clear() is not proxied to the internal dict
either (no such method).

People use (http://www.djangosnippets.org/snippets/681/)
for key in session.items(): del session[key]
which is ugly and ineffective.

As for the lifetime arguments, I hope I have proven the need for
destroy() above.

The implementation is extremely simple if new value for
session_key is not required after clearing the session. Now that
I re-think it -- although it "looks scary" -- I'm not quite sure what
the possible pitfalls of re-using the key can be as the following
looks OK to me:

Sessions are set to expire on browser close. One browser window
is open. User A logs in and fills her session with data, then logs
out but doesn't close the browser window. The logout view calls
session.destroy(), session data is destroyed, but session_key
remains the same. User B logs in using the same browser window,
session is populated with new data using the old session_key.
User B does not get any access to user A data.

If that's OK, the following is sufficient:

class SessionBase(object):
...
def destroy(self):
self._session.clear()
self.delete(self._session_key)
self.modified = True

or the less explicit (but with equal effect):

def destroy(self):
self._session.clear()
self.modified = True

Session hijacking
-----------------

Looks like this will be solved when session is either destroyed
explicitly or in login()/logout(). That would fix #6941.

session_key collisions
----------------------

Using os.urandom() instead of random.randint() provides much
better entropy and does not have the (albeit very unprobable)
initialization with equal seed problem random.randint() has.

Thus I propose the following to lessen key collision probability:

urandom = None
try:
from os import urandom
except ImportError, NotImplementedError:
import random

def _get_entropy():
"""
Returns 128 (pseudo)random bits.
"""
if urandom:
return urandom(16)
else:
# shameless copy from #1180
bytes = [chr(random.randrange(256)) for i in xrange(16)]
return bytes

class SessionBase(object):
....
def _get_new_session_key(self):
"Returns session key that isn't being used."
# The random module is seeded when this Apache child is
created.
# Use settings.SECRET_KEY as added salt. --- *** is this
necessary? ***
try:
pid = os.getpid()
except AttributeError:
# No getpid() in Jython, for example
pid = 1
while 1:
session_key = md5.new("%s%s%s%s" %
(_get_entropy(), pid, time.time(),
settings.SECRET_KEY)).hexdigest()
if not self.exists(session_key):
break
return session_key

Alternatively, the full UUID patch from #1180 could be used, but it's
quite heavy-weight, so I'm -0 on that.

This would fix #1180.

Further improvements
--------------------

I'm quite sure that most Django users use Python 2.5 (and if they
don't, they should for obmalloc in 2.5 and speed fixes in 2.5.2).
It looks like those using 2.5 deserve a pony :), namely using sha256
instead of md5 to radically cut the probability of key collisions. I
think this may not look appealing to you, but I outline it
nevertheless.

hashlib = None
try:
import hashlib
except ImportError
pass

if hashlib:
use hashlib.sha256
else:
use md5

This opens some problems though:
* should sha256 hashes be truncated to md5 length?
That would raise the probability of collisions.
* if not, session keys will be longer and not compatible between
different Python versions.

Malcolm Tredinnick

unread,
Apr 6, 2008, 7:28:36 PM4/6/08
to django-d...@googlegroups.com

On Sun, 2008-04-06 at 08:21 -0700, mrts wrote:
[...]
> My personal use case:
> ---------------------
>
> User sessions are used apart from django.auth.models.User. The
> application logic doesn't fit well with Django auth (auth
> features are not needed and create a minor security risk if an
> admin user inadvertently or maliciously enables staff status for an
> external
> user -- that plainly should not be possible). There is a separate
> custom user model for external users (no passwords as user data
> is loaded from SSL client certificate). Django auth is used
> nevertheless for admin (for internal users). The framework has
> it's own login and logout views. During login, minimal data about
> the user is loaded from SSL client certificate and stored in
> session. During logout, session data needs to be completely
> destoyed.
>
> It is paramount that there is a guarantee of no collisions in
> session keys, someone else cannot hijack the session and all data
> is destroyed after logout.
>
> CSRF middleware is used for protection during form submission
> (btw, I have some problems with it, but this is a different
> issue).
>
> The use case I had in mind when proposing the "bucket":
> -------------------------------------------------------

[...]

> So, there are two types of session data, one type is related to
> Django auth user and should be destroyed from the session when
> the user logs out. The other type does not require login and
> should remain in the session after logout.

No there are not two types of session data here. The shopping cart is
*not* session data. It transcends a single session. It is permanent data
that would be stored in the shopping cart model, which contains a
foreign key to the user. This is a case of needing to model the data
correctly, rather than trying to shoehorn it into the session model.

> > I don't see the need for an extra method here. Why isn't this just
> > something logout() would do?
>
> This is something that logout() *might* do. But considering the
> case above, I'm rather +0 for adding a destroy_session parameter
> to logout() (and login() for that matter) that defaults to False,
> or a wrapper, secure_logout()/secure_login().
>
> According to my personal use case, as auth is not used, an
> explicit session destruction mechanism is needed, thus
> destroy() is required. logout() should use destroy(), not
> vice-versa.

Your use case doesn't require extra handling at all. You have some
sessions that must be removed at logout. So your logout method calls the
delete method on the session object. It's now destroyed. Game over for
that session and no extra method is required.

Realise that I am in agreement with you that logout (and possibly login,
I haven't worked through the implications there) should be changed to
clear the session by default. There's no strong reason not to do that,
since the session is over when logout is called (I'll raise that
separately at an appropriate moment, since most people won't be
persisting this far into this thread and there are a few active threads
going on at the moment). We don't need logout_A and logout_B, we just
need to do the right thing here.

[...]

Lack of documentation in one place doesn't justify adding a whole extra
method that does the same thing as a single line of code. We're in this
fortunate position of being able to add to the documentation to fix
things like this.

> It requires the session key as parameter, so it is cumbersome to
> use.

Oh, come on! Leave the hyperbole at home. Instead of

my_session.delete()

you have to write

my_session.delete(my_session._session_key)

Hardly an onerous requirement and quite possibly something we could
change to default to self._session_key. I'll find out from Jacob why he
went with this approach in the first place. It might be an oversight, or
there might be some subtlety involved. In either case,this is both
currently usable and possibly able to made easier, in both cases without
adding a whole new method.

I'll address the implementation changes you're proposing in another post
when I have some more time later today.

Best wishes,
Malcolm

--
I don't have a solution, but I admire your problem.
http://www.pointy-stick.com/blog/

Robert Coup

unread,
Apr 6, 2008, 10:04:46 PM4/6/08
to django-d...@googlegroups.com
On Mon, Apr 7, 2008 at 11:28 AM, Malcolm Tredinnick <mal...@pointy-stick.com> wrote:
Realise that I am in agreement with you that logout (and possibly login,
I haven't worked through the implications there) should be changed to
clear the session by default. There's no strong reason not to do that,
since the session is over when logout is called.

(ignoring the new thread thing since i'm sure i'll miss it later)

Clearing at login-time I'm not at all sure about... reason is that data that is 'anonymous'  data can be transferred from a session into a user account when they login for lots of sensible uses.

Simple example: a ShoppingCart model that can be related to either a user or a session, allowing an anonymous user to shop and only login when they head to the checkout, at which point the cart is transferred from the session to the user.

Other uses could include preferences, personalisation ("looked at"), A-B testing, ...

Rob :)

mrts

unread,
Apr 7, 2008, 6:09:54 AM4/7/08
to Django developers
> Realise that I am in agreement with you that logout (and possibly login,
> I haven't worked through the implications there) should be changed to
> clear the session by default. There's no strong reason not to do that,
> since the session is over when logout is called (I'll raise that
> separately at an appropriate moment, since most people won't be
> persisting this far into this thread and there are a few active threads
> going on at the moment). We don't need logout_A and logout_B, we just
> need to do the right thing here.

Agreed, but as previously described, there should be a way to override
the default behaviour and retain session data if needed.

> Lack of documentation in one place doesn't justify adding a whole extra
> method that does the same thing as a single line of code. We're in this
> fortunate position of being able to add to the documentation to fix
> things like this.
>
> Oh, come on! Leave the hyperbole at home. Instead of
>
>         my_session.delete()
>
> you have to write
>
>         my_session.delete(my_session._session_key)
>
> Hardly an onerous requirement and quite possibly something we could
> change to default to self._session_key. I'll find out from Jacob why he
> went with this approach in the first place. It might be an oversight, or
> there might be some subtlety involved.

Well, well, well, Malcolm. An argumentum ad hominem and an incorrect
one:

def show_foo(request):
request.session['foo'] = 'bar'
request.session.delete(request.session._session_key)
return HttpResponse(request.session['foo'])

--> displays bar.

def show_foo(request):
request.session['foo'] = 'bar'
request.session.delete(request.session._session_key)
return HttpResponse(request.session['foo'])

In [1]: from django.contrib.sessions.backends.db import SessionStore
In [2]: s =
SessionStore(session_key='61a271f29a679e45aed5a5539175670f')
In [3]: s.items()
Out[3]: [('foo', 'bar'), ('bar', 'baz')]

dict.clear() needs to be called as well, otherwise delete() has zero
effect.

Note that I actually don't mind the personal arguments quite common
here, they keep people thinking and carefully checking their
statements and thus from posting utter stupidity. That is good.

So don't mind my nosiness either :) And I just love your clear
thinking and the way you solved the multiple inheritance problem.

Best regards,
Mart Sõmermaa

mrts

unread,
Apr 7, 2008, 6:28:55 AM4/7/08
to Django developers
> def show_foo(request):
> request.session['foo'] = 'bar'
> request.session.delete(request.session._session_key)
> return HttpResponse(request.session['foo'])
>
> In [1]: from django.contrib.sessions.backends.db import SessionStore
> In [2]: s =
> SessionStore(session_key='61a271f29a679e45aed5a5539175670f')
> In [3]: s.items()
> Out[3]: [('foo', 'bar'), ('bar', 'baz')]

Wrong copy-paste:

def show_foo(request):
request.session['foo'] = 'bar'
request.session.delete(request.session._session_key)
request.session['bar'] = 'baz'
# session will be saved, bringing 'foo'
# back to life

Malcolm Tredinnick

unread,
Apr 7, 2008, 5:53:35 PM4/7/08
to django-d...@googlegroups.com

On Mon, 2008-04-07 at 03:09 -0700, mrts wrote:
> > Realise that I am in agreement with you that logout (and possibly login,
> > I haven't worked through the implications there) should be changed to
> > clear the session by default. There's no strong reason not to do that,
> > since the session is over when logout is called (I'll raise that
> > separately at an appropriate moment, since most people won't be
> > persisting this far into this thread and there are a few active threads
> > going on at the moment). We don't need logout_A and logout_B, we just
> > need to do the right thing here.
>
> Agreed, but as previously described, there should be a way to override
> the default behaviour and retain session data if needed.

No, I don't see any need for this at all. Once you've logged out, the
session is over. Stuff you want to keep beyond that is not session data.

Malcolm

--
If Barbie is so popular, why do you have to buy her friends?
http://www.pointy-stick.com/blog/

Simon Blanchard

unread,
Apr 8, 2008, 12:43:42 AM4/8/08
to django-d...@googlegroups.com
If I may point to a new ticket I just created related to sessions and
race conditions
http://code.djangoproject.com/ticket/6984

It fixes a lot of weirdness I was experiencing. It is still not thread
safe though I am not sure that is an issue since in my (limited)
testing there was a one-to-one mapping between thread and session.

BTW When debugging the issue I arrived at the following logout method
to clean stuff up:

def logout(request):
session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)
request.session.delete(session_key)
request.session = None
response = HttpResponseRedirect("/clients/")
response.delete_cookie(settings.SESSION_COOKIE_NAME)
return response


Simon

mrts

unread,
Apr 8, 2008, 4:25:42 AM4/8/08
to Django developers


On Apr 8, 12:53 am, Malcolm Tredinnick <malc...@pointy-stick.com>
wrote:
> > Agreed, but as previously described, there should be a way to override
> > the default behaviour and retain session data if needed.
>
> No, I don't see any need for this at all. Once you've logged out, the
> session is over. Stuff you want to keep beyond that is not session data.

So you think "fill your shopping cart, login then logout" should empty
the shopping cart? This feels counter-intuitive, but it doesn't bite
me personally, so dismissing this case is fine by me.

Regards,
MS

Waylan Limberg

unread,
Apr 8, 2008, 10:08:25 AM4/8/08
to django-d...@googlegroups.com
No, as discussed earlier, upon login the data (shopping cart) *should*
become associated with the user, not the session. So upon logout, the
data is not lost as it is not connected to the session. To the user
the data (cart) may *appear* to be lost because they logged out and no
longer have access to the user's data, but upon logging in again, they
would be able to access it again.

Of course, for this to work one would need a carefully crafted model
(again as mentioned previously). The data (shopping cart) would need
to be attached to the session for anonymous users, but attached to the
user for logged in users. Part of logging a user in would be to make
that transition of the data from session to user. Then deleting
session data on logout becomes a non-issue.

--
----
Waylan Limberg
way...@gmail.com

Reply all
Reply to author
Forward
0 new messages