Browse Source

reorder session cookie checks to deleted, accessed, modified

pull/2288/head
David Lord 8 years ago
parent
commit
ae133aa173
No known key found for this signature in database
GPG Key ID: 7A1C87E3F5BC42A8
  1. 67
      flask/sessions.py

67
flask/sessions.py

@ -125,7 +125,8 @@ class SecureCookieSession(CallbackDict, SessionMixin):
def on_update(self): def on_update(self):
self.modified = True self.modified = True
self.accessed = True self.accessed = True
CallbackDict.__init__(self, initial, on_update)
super(SecureCookieSession, self).__init__(initial, on_update)
self.modified = False self.modified = False
self.accessed = False self.accessed = False
@ -306,22 +307,20 @@ class SessionInterface(object):
return datetime.utcnow() + app.permanent_session_lifetime return datetime.utcnow() + app.permanent_session_lifetime
def should_set_cookie(self, app, session): def should_set_cookie(self, app, session):
"""Indicates whether a cookie should be set now or not. This is """Used by session backends to determine if a ``Set-Cookie`` header
used by session backends to figure out if they should emit a should be set for this session cookie for this response. If the session
set-cookie header or not. The default behavior is controlled by has been modified, the cookie is set. If the session is permanent and
the ``SESSION_REFRESH_EACH_REQUEST`` config variable. If the ``SESSION_REFRESH_EACH_REQUEST`` config is true, the cookie is
it's set to ``False`` then a cookie is only set if the session is always set.
modified, if set to ``True`` it's always set if the session is
permanent.
This check is usually skipped if sessions get deleted. This check is usually skipped if the session was deleted.
.. versionadded:: 0.11 .. versionadded:: 0.11
""" """
if session.modified:
return True return session.modified or (
save_each = app.config['SESSION_REFRESH_EACH_REQUEST'] session.permanent and app.config['SESSION_REFRESH_EACH_REQUEST']
return save_each and session.permanent )
def open_session(self, app, request): def open_session(self, app, request):
"""This method has to be implemented and must either return ``None`` """This method has to be implemented and must either return ``None``
@ -387,28 +386,22 @@ class SecureCookieSessionInterface(SessionInterface):
domain = self.get_cookie_domain(app) domain = self.get_cookie_domain(app)
path = self.get_cookie_path(app) path = self.get_cookie_path(app)
if session.accessed: # If the session is modified to be empty, remove the cookie.
# If the session is empty, return without setting the cookie.
response.headers.add('Vary', 'Cookie')
else:
# Delete case. If there is no session we bail early.
# If the session was modified to be empty we remove the
# whole cookie.
if not session: if not session:
if session.modified: if session.modified:
response.delete_cookie(app.session_cookie_name, response.delete_cookie(
domain=domain, path=path) app.session_cookie_name,
domain=domain,
path=path
)
return return
# Modification case. There are upsides and downsides to # Add a "Vary: Cookie" header if the session was accessed at all.
# emitting a set-cookie header each request. The behavior if session.accessed:
# is controlled by the :meth:`should_set_cookie` method response.headers.add('Vary', 'Cookie')
# which performs a quick check to figure out if the cookie
# should be set or not. This is controlled by the
# SESSION_REFRESH_EACH_REQUEST config flag as well as
# the permanent flag on the session itself.
if not self.should_set_cookie(app, session): if not self.should_set_cookie(app, session):
return return
@ -416,6 +409,12 @@ class SecureCookieSessionInterface(SessionInterface):
secure = self.get_cookie_secure(app) secure = self.get_cookie_secure(app)
expires = self.get_expiration_time(app, session) expires = self.get_expiration_time(app, session)
val = self.get_signing_serializer(app).dumps(dict(session)) val = self.get_signing_serializer(app).dumps(dict(session))
response.set_cookie(app.session_cookie_name, val, response.set_cookie(
expires=expires, httponly=httponly, app.session_cookie_name,
domain=domain, path=path, secure=secure) val,
expires=expires,
httponly=httponly,
domain=domain,
path=path,
secure=secure
)

Loading…
Cancel
Save