Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added finer control over the session cookie parameters

  • Loading branch information...
commit ccf464189b116ea4ee458c2ccb24d64f9272e25b 1 parent 23bf263
@mitsuhiko authored
View
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
-------------
View
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
----------------------
View
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
View
28 flask/sessions.py
@@ -123,16 +123,33 @@ def get_cookie_domain(self, app):
"""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 @@ def save_session(self, app, session, response):
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)
View
22 flask/testsuite/basic.py
@@ -207,6 +207,28 @@ def index():
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):
Please sign in to comment.
Something went wrong with that request. Please try again.