Browse Source

Added finer control over the session cookie parameters

pull/311/head
Armin Ronacher 13 years ago
parent
commit
ccf464189b
  1. 1
      CHANGES
  2. 18
      docs/config.rst
  3. 6
      flask/app.py
  4. 28
      flask/sessions.py
  5. 22
      flask/testsuite/basic.py

1
CHANGES

@ -42,6 +42,7 @@ Relase date to be decided, codename to be chosen.
pluggable (class based) views.
- Fixed an issue where the test client if used with the with statement did not
trigger the execution of the teardown handlers.
- Added finer control over the session cookie parameters.
Version 0.7.3
-------------

18
docs/config.rst

@ -70,6 +70,20 @@ The following configuration values are used internally by Flask:
very risky).
``SECRET_KEY`` the secret key
``SESSION_COOKIE_NAME`` the name of the session cookie
``SESSION_COOKIE_DOMAIN`` the domain for the session cookie. If
this is not set, the cookie will be
valid for all subdomains of
``SERVER_NAME``.
``SESSION_COOKIE_PATH`` the path for the session cookie. If
this is not set the cookie will be valid
for all of ``APPLICATION_ROOT`` or if
that is not set for ``'/'``.
``SESSION_COOKIE_HTTPONLY`` controls if the cookie should be set
with the httponly flag. Defaults to
`True`.
``SESSION_COOKIE_SECURE`` controls if the cookie should be set
with the secure flag. Defaults to
`False`.
``PERMANENT_SESSION_LIFETIME`` the lifetime of a permanent session as
:class:`datetime.timedelta` object.
``USE_X_SENDFILE`` enable/disable x-sendfile
@ -142,7 +156,9 @@ The following configuration values are used internally by Flask:
.. versionadded:: 0.8
``TRAP_BAD_REQUEST_ERRORS``, ``TRAP_HTTP_EXCEPTIONS``,
``APPLICATION_ROOT``
``APPLICATION_ROOT``, ``SESSION_COOKIE_DOMAIN``,
``SESSION_COOKIE_PATH``, ``SESSION_COOKIE_HTTPONLY``,
``SESSION_COOKIE_SECURE``
Configuring from Files
----------------------

6
flask/app.py

@ -231,12 +231,16 @@ class Flask(_PackageBoundObject):
'PROPAGATE_EXCEPTIONS': None,
'PRESERVE_CONTEXT_ON_EXCEPTION': None,
'SECRET_KEY': None,
'SESSION_COOKIE_NAME': 'session',
'PERMANENT_SESSION_LIFETIME': timedelta(days=31),
'USE_X_SENDFILE': False,
'LOGGER_NAME': None,
'SERVER_NAME': None,
'APPLICATION_ROOT': None,
'SESSION_COOKIE_NAME': 'session',
'SESSION_COOKIE_DOMAIN': None,
'SESSION_COOKIE_PATH': None,
'SESSION_COOKIE_HTTPONLY': True,
'SESSION_COOKIE_SECURE': False,
'MAX_CONTENT_LENGTH': None,
'TRAP_BAD_REQUEST_ERRORS': False,
'TRAP_HTTP_EXCEPTIONS': False

28
flask/sessions.py

@ -123,16 +123,33 @@ class SessionInterface(object):
"""Helpful helper method that returns the cookie domain that should
be used for the session cookie if session cookies are used.
"""
if app.config['SESSION_COOKIE_DOMAIN'] is not None:
return app.config['SESSION_COOKIE_DOMAIN']
if app.config['SERVER_NAME'] is not None:
# chop of the port which is usually not supported by browsers
return '.' + app.config['SERVER_NAME'].rsplit(':', 1)[0]
def get_cookie_path(self, app):
"""Returns the path for which the cookie should be valid. The
default implementation uses the value from the ``APPLICATION_ROOT``
configuration variable or uses ``/`` if it's `None`.
default implementation uses the value from the SESSION_COOKIE_PATH``
config var if it's set, and falls back to ``APPLICATION_ROOT`` or
uses ``/`` if it's `None`.
"""
return app.config['APPLICATION_ROOT'] or '/'
return app.config['SESSION_COOKIE_PATH'] or \
app.config['APPLICATION_ROOT'] or '/'
def get_cookie_httponly(self, app):
"""Returns True if the session cookie should be httponly. This
currently just returns the value of the ``SESSION_COOKIE_HTTPONLY``
config var.
"""
return app.config['SESSION_COOKIE_HTTPONLY']
def get_cookie_secure(self, app):
"""Returns True if the cookie should be secure. This currently
just returns the value of the ``SESSION_COOKIE_SECURE`` setting.
"""
return app.config['SESSION_COOKIE_SECURE']
def get_expiration_time(self, app, session):
"""A helper method that returns an expiration date for the session
@ -177,9 +194,12 @@ class SecureCookieSessionInterface(SessionInterface):
expires = self.get_expiration_time(app, session)
domain = self.get_cookie_domain(app)
path = self.get_cookie_path(app)
httponly = self.get_cookie_httponly(app)
secure = self.get_cookie_secure(app)
if session.modified and not session:
response.delete_cookie(app.session_cookie_name, path=path,
domain=domain)
else:
session.save_cookie(response, app.session_cookie_name, path=path,
expires=expires, httponly=True, domain=domain)
expires=expires, httponly=httponly,
secure=secure, domain=domain)

22
flask/testsuite/basic.py

@ -207,6 +207,28 @@ class BasicFunctionalityTestCase(FlaskTestCase):
rv = app.test_client().get('/', 'http://example.com:8080/')
self.assert_('path=/bar' in rv.headers['set-cookie'].lower())
def test_session_using_session_settings(self):
app = flask.Flask(__name__)
app.config.update(
SECRET_KEY='foo',
SERVER_NAME='www.example.com:8080',
APPLICATION_ROOT='/test',
SESSION_COOKIE_DOMAIN='.example.com',
SESSION_COOKIE_HTTPONLY=False,
SESSION_COOKIE_SECURE=True,
SESSION_COOKIE_PATH='/'
)
@app.route('/')
def index():
flask.session['testing'] = 42
return 'Hello World'
rv = app.test_client().get('/', 'http://www.example.com:8080/test/')
cookie = rv.headers['set-cookie'].lower()
self.assert_('domain=.example.com' in cookie)
self.assert_('path=/;' in cookie)
self.assert_('secure' in cookie)
self.assert_('httponly' not in cookie)
def test_missing_session(self):
app = flask.Flask(__name__)
def expect_exception(f, *args, **kwargs):

Loading…
Cancel
Save