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.
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).
> 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.
> 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?
> > 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:
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.
> 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
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.
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?
> 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
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.
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.)
> 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.