ソースを参照

Refs #31842 -- Removed DEFAULT_HASHING_ALGORITHM transitional setting.

Per deprecation timeline.
Mariusz Felisiak 4 年 前
コミット
0aa6a602b2

+ 0 - 13
django/conf/__init__.py

@@ -9,22 +9,14 @@ for a list of all possible variables.
 import importlib
 import os
 import time
-import warnings
 from pathlib import Path
 
 from django.conf import global_settings
 from django.core.exceptions import ImproperlyConfigured
-from django.utils.deprecation import RemovedInDjango40Warning
 from django.utils.functional import LazyObject, empty
 
 ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
 
-DEFAULT_HASHING_ALGORITHM_DEPRECATED_MSG = (
-    'The DEFAULT_HASHING_ALGORITHM transitional setting is deprecated. '
-    'Support for it and tokens, cookies, sessions, and signatures that use '
-    'SHA-1 hashing algorithm will be removed in Django 4.0.'
-)
-
 
 class SettingsReference(str):
     """
@@ -164,9 +156,6 @@ class Settings:
                 setattr(self, setting, setting_value)
                 self._explicit_settings.add(setting)
 
-        if self.is_overridden('DEFAULT_HASHING_ALGORITHM'):
-            warnings.warn(DEFAULT_HASHING_ALGORITHM_DEPRECATED_MSG, RemovedInDjango40Warning)
-
         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.
@@ -210,8 +199,6 @@ class UserSettingsHolder:
 
     def __setattr__(self, name, value):
         self._deleted.discard(name)
-        if name == 'DEFAULT_HASHING_ALGORITHM':
-            warnings.warn(DEFAULT_HASHING_ALGORITHM_DEPRECATED_MSG, RemovedInDjango40Warning)
         super().__setattr__(name, value)
 
     def __delattr__(self, name):

+ 0 - 6
django/conf/global_settings.py

@@ -439,12 +439,6 @@ WSGI_APPLICATION = None
 # you may be opening yourself up to a security risk.
 SECURE_PROXY_SSL_HEADER = None
 
-# Default hashing algorithm to use for encoding cookies, password reset tokens
-# in the admin site, user sessions, and signatures. It's a transitional setting
-# helpful in migrating multiple instance of the same project to Django 3.1+.
-# Algorithm must be 'sha1' or 'sha256'.
-DEFAULT_HASHING_ALGORITHM = 'sha256'
-
 ##############
 # MIDDLEWARE #
 ##############

+ 1 - 5
django/contrib/auth/base_user.py

@@ -4,7 +4,6 @@ not in INSTALLED_APPS.
 """
 import unicodedata
 
-from django.conf import settings
 from django.contrib.auth import password_validation
 from django.contrib.auth.hashers import (
     check_password, is_password_usable, make_password,
@@ -129,10 +128,7 @@ class AbstractBaseUser(models.Model):
         return salted_hmac(
             key_salt,
             self.password,
-            # RemovedInDjango40Warning: when the deprecation ends, replace
-            # with:
-            # algorithm='sha256',
-            algorithm=settings.DEFAULT_HASHING_ALGORITHM,
+            algorithm='sha256',
         ).hexdigest()
 
     @classmethod

+ 1 - 3
django/contrib/auth/tokens.py

@@ -16,9 +16,7 @@ class PasswordResetTokenGenerator:
 
     def __init__(self):
         self.secret = self.secret or settings.SECRET_KEY
-        # RemovedInDjango40Warning: when the deprecation ends, replace with:
-        # self.algorithm = self.algorithm or 'sha256'
-        self.algorithm = self.algorithm or settings.DEFAULT_HASHING_ALGORITHM
+        self.algorithm = self.algorithm or 'sha256'
 
     def make_token(self, user):
         """

+ 0 - 13
django/core/checks/security/base.py

@@ -119,11 +119,6 @@ E023 = Error(
     id='security.E023',
 )
 
-E100 = Error(
-    "DEFAULT_HASHING_ALGORITHM must be 'sha1' or 'sha256'.",
-    id='security.E100',
-)
-
 
 def _security_middleware():
     return 'django.middleware.security.SecurityMiddleware' in settings.MIDDLEWARE
@@ -237,11 +232,3 @@ def check_referrer_policy(app_configs, **kwargs):
         if not values <= REFERRER_POLICY_VALUES:
             return [E023]
     return []
-
-
-# RemovedInDjango40Warning
-@register(Tags.security)
-def check_default_hashing_algorithm(app_configs, **kwargs):
-    if settings.DEFAULT_HASHING_ALGORITHM not in {'sha1', 'sha256'}:
-        return [E100]
-    return []

+ 1 - 3
django/core/signing.py

@@ -129,9 +129,7 @@ class Signer:
                 'only A-z0-9-_=)' % sep,
             )
         self.salt = salt or '%s.%s' % (self.__class__.__module__, self.__class__.__name__)
-        # RemovedInDjango40Warning: when the deprecation ends, replace with:
-        # self.algorithm = algorithm or 'sha256'
-        self.algorithm = algorithm or settings.DEFAULT_HASHING_ALGORITHM
+        self.algorithm = algorithm or 'sha256'
 
     def signature(self, value):
         return base64_hmac(self.salt + 'signer', value, self.key, algorithm=self.algorithm)

+ 2 - 2
docs/ref/checks.txt

@@ -494,8 +494,8 @@ The following checks are run if you use the :option:`check --deploy` option:
 The following checks verify that your security-related settings are correctly
 configured:
 
-* **security.E100**: :setting:`DEFAULT_HASHING_ALGORITHM` must be ``'sha1'`` or
-  ``'sha256'``.
+* **security.E100**: ``DEFAULT_HASHING_ALGORITHM`` must be ``'sha1'`` or
+  ``'sha256'``. *This check appeared in Django 3.1 and 3.2*.
 * **security.E101**: The CSRF failure view ``'path.to.view'`` does not take the
   correct number of arguments.
 * **security.E102**: The CSRF failure view ``'path.to.view'`` could not be

+ 0 - 19
docs/ref/settings.txt

@@ -1291,25 +1291,6 @@ Default email address to use for various automated correspondence from the
 site manager(s). This doesn't include error messages sent to :setting:`ADMINS`
 and :setting:`MANAGERS`; for that, see :setting:`SERVER_EMAIL`.
 
-.. setting:: DEFAULT_HASHING_ALGORITHM
-
-``DEFAULT_HASHING_ALGORITHM``
------------------------------
-
-Default: ``'sha256'``
-
-Default hashing algorithm to use for encoding cookies, password reset tokens in
-the admin site, user sessions, and signatures created by
-:class:`django.core.signing.Signer` and :meth:`django.core.signing.dumps`.
-Algorithm must be ``'sha1'`` or ``'sha256'``. See
-:ref:`release notes <default-hashing-algorithm-usage>` for usage details.
-
-.. deprecated:: 3.1
-
-    This transitional setting is deprecated. Support for it and tokens,
-    cookies, sessions, and signatures that use SHA-1 hashing algorithm will be
-    removed in Django 4.0.
-
 .. setting:: DEFAULT_INDEX_TABLESPACE
 
 ``DEFAULT_INDEX_TABLESPACE``

+ 7 - 7
docs/releases/3.1.txt

@@ -101,17 +101,17 @@ of this release <deprecated-jsonfield>`.
 ``DEFAULT_HASHING_ALGORITHM`` settings
 --------------------------------------
 
-The new :setting:`DEFAULT_HASHING_ALGORITHM` transitional setting allows
-specifying the default hashing algorithm to use for encoding cookies, password
-reset tokens in the admin site, user sessions, and signatures created by
+The new ``DEFAULT_HASHING_ALGORITHM`` transitional setting allows specifying
+the default hashing algorithm to use for encoding cookies, password reset
+tokens in the admin site, user sessions, and signatures created by
 :class:`django.core.signing.Signer` and :meth:`django.core.signing.dumps`.
 
 Support for SHA-256 was added in Django 3.1. If you are upgrading multiple
 instances of the same project to Django 3.1, you should set
-:setting:`DEFAULT_HASHING_ALGORITHM` to ``'sha1'`` during the transition, in
-order to allow compatibility with the older versions of Django. Note that this
-requires Django 3.1.1+. Once the transition to 3.1 is complete you can stop
-overriding :setting:`DEFAULT_HASHING_ALGORITHM`.
+``DEFAULT_HASHING_ALGORITHM`` to ``'sha1'`` during the transition, in order to
+allow compatibility with the older versions of Django. Note that this requires
+Django 3.1.1+. Once the transition to 3.1 is complete you can stop overriding
+``DEFAULT_HASHING_ALGORITHM``.
 
 This setting is deprecated as of this release, because support for tokens,
 cookies, sessions, and signatures that use SHA-1 algorithm will be removed in

+ 2 - 0
docs/releases/4.0.txt

@@ -323,3 +323,5 @@ to remove usage of these features.
 * ``django.contrib.postgres.forms.JSONField`` is removed.
 
 * The ``{% ifequal %}`` and ``{% ifnotequal %}`` template tags are removed.
+
+* The ``DEFAULT_HASHING_ALGORITHM`` transitional setting is removed.

+ 1 - 10
tests/auth_tests/test_middleware.py

@@ -1,10 +1,7 @@
-from django.contrib.auth import HASH_SESSION_KEY
 from django.contrib.auth.middleware import AuthenticationMiddleware
 from django.contrib.auth.models import User
 from django.http import HttpRequest, HttpResponse
-from django.test import TestCase, override_settings
-from django.test.utils import ignore_warnings
-from django.utils.deprecation import RemovedInDjango40Warning
+from django.test import TestCase
 
 
 class TestAuthenticationMiddleware(TestCase):
@@ -24,12 +21,6 @@ class TestAuthenticationMiddleware(TestCase):
         self.assertIsNotNone(self.request.user)
         self.assertFalse(self.request.user.is_anonymous)
 
-    @ignore_warnings(category=RemovedInDjango40Warning)
-    def test_session_default_hashing_algorithm(self):
-        hash_session = self.client.session[HASH_SESSION_KEY]
-        with override_settings(DEFAULT_HASHING_ALGORITHM='sha1'):
-            self.assertNotEqual(hash_session, self.user.get_session_auth_hash())
-
     def test_changed_password_invalidates_session(self):
         # After password change, user should be anonymous
         self.user.set_password('new_password')

+ 0 - 11
tests/auth_tests/test_tokens.py

@@ -4,8 +4,6 @@ from django.conf import settings
 from django.contrib.auth.models import User
 from django.contrib.auth.tokens import PasswordResetTokenGenerator
 from django.test import TestCase
-from django.test.utils import ignore_warnings
-from django.utils.deprecation import RemovedInDjango40Warning
 
 from .models import CustomEmailField
 
@@ -113,12 +111,3 @@ class TokenGeneratorTest(TestCase):
         # Tokens created with a different secret don't validate.
         self.assertIs(p0.check_token(user, tk1), False)
         self.assertIs(p1.check_token(user, tk0), False)
-
-    @ignore_warnings(category=RemovedInDjango40Warning)
-    def test_token_default_hashing_algorithm(self):
-        user = User.objects.create_user('tokentestuser', 'test2@example.com', 'testpw')
-        with self.settings(DEFAULT_HASHING_ALGORITHM='sha1'):
-            generator = PasswordResetTokenGenerator()
-            self.assertEqual(generator.algorithm, 'sha1')
-            token = generator.make_token(user)
-            self.assertIs(generator.check_token(user, token), True)

+ 0 - 55
tests/deprecation/test_default_hashing_algorithm.py

@@ -1,55 +0,0 @@
-import sys
-from types import ModuleType
-
-from django.conf import (
-    DEFAULT_HASHING_ALGORITHM_DEPRECATED_MSG, Settings, settings,
-)
-from django.core.checks.security import base as security_base
-from django.test import TestCase, ignore_warnings
-from django.utils.deprecation import RemovedInDjango40Warning
-
-
-class DefaultHashingAlgorithmDeprecationTests(TestCase):
-    msg = DEFAULT_HASHING_ALGORITHM_DEPRECATED_MSG
-
-    def test_override_settings_warning(self):
-        with self.assertRaisesMessage(RemovedInDjango40Warning, self.msg):
-            with self.settings(DEFAULT_HASHING_ALGORITHM='sha1'):
-                pass
-
-    def test_settings_init_warning(self):
-        settings_module = ModuleType('fake_settings_module')
-        settings_module.SECRET_KEY = 'foo'
-        settings_module.DEFAULT_HASHING_ALGORITHM = 'sha1'
-        sys.modules['fake_settings_module'] = settings_module
-        try:
-            with self.assertRaisesMessage(RemovedInDjango40Warning, self.msg):
-                Settings('fake_settings_module')
-        finally:
-            del sys.modules['fake_settings_module']
-
-    def test_access(self):
-        # Warning is not raised on access.
-        self.assertEqual(settings.DEFAULT_HASHING_ALGORITHM, 'sha256')
-
-    @ignore_warnings(category=RemovedInDjango40Warning)
-    def test_system_check_invalid_value(self):
-        tests = [
-            None,
-            256,
-            'invalid',
-            'md5',
-            'sha512',
-        ]
-        for value in tests:
-            with self.subTest(value=value), self.settings(DEFAULT_HASHING_ALGORITHM=value):
-                self.assertEqual(
-                    security_base.check_default_hashing_algorithm(None),
-                    [security_base.E100],
-                )
-
-    @ignore_warnings(category=RemovedInDjango40Warning)
-    def test_system_check_valid_value(self):
-        for value in ['sha1', 'sha256']:
-            with self.subTest(value=value), self.settings(DEFAULT_HASHING_ALGORITHM=value):
-                self.assertEqual(security_base.check_default_hashing_algorithm(None), [])

+ 0 - 13
tests/messages_tests/test_cookie.py

@@ -9,9 +9,7 @@ from django.contrib.messages.storage.cookie import (
 )
 from django.core.signing import get_cookie_signer
 from django.test import SimpleTestCase, override_settings
-from django.test.utils import ignore_warnings
 from django.utils.crypto import get_random_string
-from django.utils.deprecation import RemovedInDjango40Warning
 from django.utils.safestring import SafeData, mark_safe
 
 from .base import BaseTests
@@ -193,14 +191,3 @@ class CookieTests(BaseTests, SimpleTestCase):
         encoded_messages = signer.sign(value)
         decoded_messages = storage._decode(encoded_messages)
         self.assertEqual(messages, decoded_messages)
-
-    @ignore_warnings(category=RemovedInDjango40Warning)
-    def test_default_hashing_algorithm(self):
-        messages = Message(constants.DEBUG, ['this', 'that'])
-        with self.settings(DEFAULT_HASHING_ALGORITHM='sha1'):
-            storage = self.get_storage()
-            encoded = storage._encode(messages)
-            decoded = storage._decode(encoded)
-            self.assertEqual(decoded, messages)
-        storage_default = self.get_storage()
-        self.assertNotEqual(encoded, storage_default._encode(messages))

+ 1 - 17
tests/signing/tests.py

@@ -2,9 +2,8 @@ import datetime
 
 from django.core import signing
 from django.test import SimpleTestCase
-from django.test.utils import freeze_time, ignore_warnings
+from django.test.utils import freeze_time
 from django.utils.crypto import InvalidAlgorithm
-from django.utils.deprecation import RemovedInDjango40Warning
 
 
 class TestSigner(SimpleTestCase):
@@ -53,14 +52,6 @@ class TestSigner(SimpleTestCase):
             'VzO9_jVu7R-VkqknHYNvw',
         )
 
-    @ignore_warnings(category=RemovedInDjango40Warning)
-    def test_default_hashing_algorithm(self):
-        signer = signing.Signer('predictable-secret', algorithm='sha1')
-        signature_sha1 = signer.signature('hello')
-        with self.settings(DEFAULT_HASHING_ALGORITHM='sha1'):
-            signer = signing.Signer('predictable-secret')
-            self.assertEqual(signer.signature('hello'), signature_sha1)
-
     def test_invalid_algorithm(self):
         signer = signing.Signer('predictable-secret', algorithm='whatever')
         msg = "'whatever' is not an algorithm accepted by the hashlib module."
@@ -143,13 +134,6 @@ class TestSigner(SimpleTestCase):
             self.assertNotEqual(o, signing.dumps(o, compress=True))
             self.assertEqual(o, signing.loads(signing.dumps(o, compress=True)))
 
-    @ignore_warnings(category=RemovedInDjango40Warning)
-    def test_dumps_loads_default_hashing_algorithm_sha1(self):
-        value = 'a string \u2020'
-        with self.settings(DEFAULT_HASHING_ALGORITHM='sha1'):
-            signed = signing.dumps(value)
-            self.assertEqual(signing.loads(signed), value)
-
     def test_decode_detects_tampering(self):
         "loads should raise exception for tampered objects"
         transforms = (