#18194: File-based session never expire
----------------------------------+-------------------------------------
     Reporter:  ej                |                    Owner:  aaugustin
         Type:  Bug               |                   Status:  new
    Component:  contrib.sessions  |                  Version:  master
     Severity:  Release blocker   |               Resolution:
     Keywords:                    |             Triage Stage:  Accepted
    Has patch:  1                 |      Needs documentation:  0
  Needs tests:  0                 |  Patch needs improvement:  0
Easy pickings:  0                 |                    UI/UX:  0
----------------------------------+-------------------------------------

Comment (by aaugustin):

 I've worked on this ticket today. Here's an analysis of how session
 expiration is handled by django.contrib.sessions, and specifically by the
 built-in backends.

 Expiration is handled both client-side (by setting cookie expiry) and
 server-side (because we don't want to keep stale data forever).

 This ticket is about synchronizing server-side expiration with client-side
 expiration, especially for the file backend. Historically Django hasn't
 paid much attention to server-side expiration.

 ----

 The default session expiration policy is:
 - client-side: expire after `settings.SESSION_COOKIE_AGE` seconds if
 `settings.SESSION_EXPIRE_AT_BROWSER_CLOSE = False` (default), at browser
 close otherwise
 - server-side: expire after `settings.SESSION_COOKIE_AGE` (no matter the
 value of `settings.SESSION_EXPIRE_AT_BROWSER_CLOSE = False`)

 When a non-default expiration is set with `session.set_expiry(...)`, it is
 saved in the session under the `_session_expiry` key. The semantic of this
 value is:
 - if it's missing or `None`: use the default expiration policy described
 above
 - if it's `0`: expire at browser close (client side), after
 `settings.SESSION_COOKIE_AGE` (server side)
 - if it's an `int`: expire in that many seconds (both sides)
 - if it's a `datetime`: expire at that time (both sides)

 This analysis is based on the implementation of `SessionMiddleware`,
 `session.get_expire_at_browser_close()`, `session.get_expiry_age()` (which
 controls client-side expiry) and `session.get_expiry_date()` (which
 controls server-side expiry).

 '''tl;dr''' The expiry date of a session is always defined by
 `session.get_expiry_date()` / `session.get_expiry_age()` '''at the time
 the session is saved''' — because it relies on `timezone.now()` in some
 cases.

 ----

 How do the various backends deal with that?

 - '''cache''': the expiry age is computed and passed to the cache engine.
 The cache engine is responsible for not returning stale data. Since
 correct expiry is a major feature for a cache, I think we can rely on
 cache engine to enforce expiry properly. There's no need to clear expired
 sessions, the cache does it by itself.

 - '''cached_db''': there's a bug here — expiry age is hardcoded to
 `settings.SESSION_COOKIE_AGE` instead of `session.get_expiry_age()`.
 Otherwise it should work like '''cache''' and '''db'''.

 - '''db''': the session expiry date is computed and stored alongside the
 session data when the session is saved. Only sessions whose expiry dates
 are in the future can be re-loaded. Sessions whose expiry dates are in the
 past can be cleared.

 - '''file''': the session expiry date isn't stored. It can be rebuilt with
 the algorithm of `session.get_expiry_age()`, by substituting the file's
 last modification time to `timezone.now()`. The patches above attempt to
 do that in order to clear expired sessions.

 - '''signed_cookies''': server-side expiration is provided by timestamping
 and signing the cookies. However non-default expiry dates aren't handled;
 the maximum expiration time is hardcoded at `settings.SESSION_COOKIE_AGE`.
 There's no need to clear expired sessions because they're stored client-
 side.

 ----

 That was a bit long but necessary to frame this ticket :)

 Now there are two actions:
 1) Clear expired sessions with the file backend. The patches above are on
 the right track. This depends on #18978.
 2) In the longer term, always store the expiration date in the session and
 refuse to load an expired session in `SessionBase.load`. This is already
 how signed cookies work. It overlaps significantly with `_session_expiry`
 as described above. It's a major refactor of `django.contrib.sessions`
 that will require backwards-compatibility.

 Since 1.5 is now feature-frozen, let's restrict this ticket to 1) and
 create a new ticket for 2).

-- 
Ticket URL: <https://code.djangoproject.com/ticket/18194#comment:12>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-updates@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to