Commit b6ea059b authored by Tim Graham's avatar Tim Graham
Browse files

Fixed #23957 -- Started deprecation toward requiring session verification.

Thanks Carl Meyer for review.
parent 1d3e41e1
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -9,9 +9,11 @@ a list of all possible variables.
import importlib
import os
import time     # Needed for Windows
import warnings

from django.conf import global_settings
from django.core.exceptions import ImproperlyConfigured
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.functional import LazyObject, empty
from django.utils import six

@@ -110,6 +112,16 @@ class Settings(BaseSettings):
        if not self.SECRET_KEY:
            raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.")

        if ('django.contrib.auth.middleware.AuthenticationMiddleware' in self.MIDDLEWARE_CLASSES and
                'django.contrib.auth.middleware.SessionAuthenticationMiddleware' not in self.MIDDLEWARE_CLASSES):
            warnings.warn(
                "Session verification will become mandatory in Django 2.0. "
                "Please add 'django.contrib.auth.middleware.SessionAuthenticationMiddleware' "
                "to your MIDDLEWARE_CLASSES setting when you are ready to opt-in after "
                "reading the upgrade considerations in the 1.8 release notes.",
                RemovedInDjango20Warning
            )

        if hasattr(time, 'tzset') and self.TIME_ZONE:
            # When we can, attempt to validate the timezone. If we can't find
            # this file, no check happens and it's harmless.
+4 −0
Original line number Diff line number Diff line
@@ -95,6 +95,10 @@ details on these changes.
  * ``django.shortcuts.render()``
  * ``django.shortcuts.render_to_response()``

* Session verification will be enabled regardless of whether or not
  ``'django.contrib.auth.middleware.SessionAuthenticationMiddleware'`` is in
  ``MIDDLEWARE_CLASSES``.

.. _deprecation-removed-in-1.9:

1.9
+15 −0
Original line number Diff line number Diff line
@@ -1158,6 +1158,21 @@ The default value of the
:attr:`RedirectView.permanent <django.views.generic.base.RedirectView.permanent>`
attribute will change from ``True`` to ``False`` in Django 1.9.

Using ``AuthenticationMiddleware`` without ``SessionAuthenticationMiddleware``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:class:`django.contrib.auth.middleware.SessionAuthenticationMiddleware` was
added in Django 1.7. In Django 1.7.2, its functionality was moved to
``auth.get_user()`` and, for backwards compatibility, enabled only if
``'django.contrib.auth.middleware.SessionAuthenticationMiddleware'`` appears in
:setting:`MIDDLEWARE_CLASSES`.

In Django 2.0, session verification will be enabled regardless of whether or not
``SessionAuthenticationMiddleware`` is enabled (at which point
``SessionAuthenticationMiddleware`` will have no significance). You can add it
to your ``MIDDLEWARE_CLASSES`` sometime before then to opt-in. Please read the
:ref:`upgrade considerations <session-invalidation-on-password-change>` first.

.. removed-features-1.8:

Features removed in 1.8
+6 −0
Original line number Diff line number Diff line
@@ -612,6 +612,12 @@ Session invalidation on password change
    is enabled in :setting:`MIDDLEWARE_CLASSES`. It's included if
    ``settings.py`` was generated by :djadmin:`startproject` on Django ≥ 1.7.

    Session verification will become mandatory in Django 2.0 regardless of
    whether or not ``SessionAuthenticationMiddleware`` is enabled. If you have
    a pre-1.7 project or one generated using a template that doesn't include
    ``SessionAuthenticationMiddleware``, consider enabling it before then after
    reading the upgrade considerations below.

If your :setting:`AUTH_USER_MODEL` inherits from
:class:`~django.contrib.auth.models.AbstractBaseUser` or implements its own
:meth:`~django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash()`
+45 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ from django.http import HttpRequest
from django.test import (SimpleTestCase, TransactionTestCase, TestCase,
    modify_settings, override_settings, signals)
from django.utils import six
from django.utils.encoding import force_text


@modify_settings(ITEMS={
@@ -464,3 +465,47 @@ class TestTupleSettings(unittest.TestCase):
            finally:
                del sys.modules['fake_settings_module']
                delattr(settings_module, setting)


class TestSessionVerification(unittest.TestCase):

    def setUp(self):
        self.settings_module = ModuleType('fake_settings_module')
        self.settings_module.SECRET_KEY = 'foo'

    def tearDown(self):
        if 'fake_settings_module' in sys.modules:
            del sys.modules['fake_settings_module']

    def test_session_verification_deprecation_no_verification(self):
        self.settings_module.MIDDLEWARE_CLASSES = ['django.contrib.auth.middleware.AuthenticationMiddleware']
        sys.modules['fake_settings_module'] = self.settings_module
        with warnings.catch_warnings(record=True) as warn:
            warnings.filterwarnings('always')
            Settings('fake_settings_module')
        self.assertEqual(
            force_text(warn[0].message),
            "Session verification will become mandatory in Django 2.0. "
            "Please add 'django.contrib.auth.middleware.SessionAuthenticationMiddleware' "
            "to your MIDDLEWARE_CLASSES setting when you are ready to opt-in after "
            "reading the upgrade considerations in the 1.8 release notes.",
        )

    def test_session_verification_deprecation_both(self):
        self.settings_module.MIDDLEWARE_CLASSES = [
            'django.contrib.auth.middleware.AuthenticationMiddleware',
            'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
        ]
        sys.modules['fake_settings_module'] = self.settings_module
        with warnings.catch_warnings(record=True) as warn:
            warnings.filterwarnings('always')
            Settings('fake_settings_module')
        self.assertEqual(len(warn), 0)

    def test_session_verification_deprecation_neither(self):
        self.settings_module.MIDDLEWARE_CLASSES = []
        sys.modules['fake_settings_module'] = self.settings_module
        with warnings.catch_warnings(record=True) as warn:
            warnings.filterwarnings('always')
            Settings('fake_settings_module')
        self.assertEqual(len(warn), 0)