diff --git a/django/contrib/auth/backends.py b/django/contrib/auth/backends.py
index 6b31f72..4ee326b 100644
|
a
|
b
|
class ModelBackend(object):
|
| 10 | 10 | |
| 11 | 11 | def authenticate(self, username=None, password=None, **kwargs): |
| 12 | 12 | UserModel = get_user_model() |
| | 13 | |
| | 14 | user = UserModel() |
| | 15 | |
| 13 | 16 | if username is None: |
| 14 | 17 | username = kwargs.get(UserModel.USERNAME_FIELD) |
| 15 | 18 | try: |
| … |
… |
class ModelBackend(object):
|
| 17 | 20 | if user.check_password(password): |
| 18 | 21 | return user |
| 19 | 22 | except UserModel.DoesNotExist: |
| | 23 | #This call to set password is used to force the hasher to run. |
| | 24 | #It helps to even out the timing between a successful and |
| | 25 | #unsuccessful authentication attempt, helping to mitigate a timing |
| | 26 | #vuln. |
| | 27 | user.set_password(password) |
| 20 | 28 | return None |
| 21 | 29 | |
| 22 | 30 | def get_group_permissions(self, user_obj, obj=None): |
diff --git a/django/contrib/auth/tests/test_auth_backends.py b/django/contrib/auth/tests/test_auth_backends.py
index fc5a80e..aa69220 100644
|
a
|
b
|
from django.contrib.auth import authenticate, get_user
|
| 12 | 12 | from django.http import HttpRequest |
| 13 | 13 | from django.test import TestCase |
| 14 | 14 | from django.test.utils import override_settings |
| | 15 | from django.contrib.auth.hashers import MD5PasswordHasher |
| 15 | 16 | |
| | 17 | """ |
| | 18 | Mock hasher which counts number of times hashes are computed |
| | 19 | |
| | 20 | Used in test_authentication_timing |
| | 21 | |
| | 22 | Refs #20760 |
| | 23 | """ |
| | 24 | class MockHasher(MD5PasswordHasher): |
| | 25 | def __init__(self): |
| | 26 | MockHasher.hash_count = 0 |
| | 27 | |
| | 28 | def encode(self, password, salt, iterations=None): |
| | 29 | MockHasher.hash_count = MockHasher.hash_count + 1 |
| | 30 | return super(MockHasher, self).encode(password, salt, iterations) |
| 16 | 31 | |
| 17 | 32 | class BaseModelBackendTest(object): |
| 18 | 33 | """ |
| … |
… |
class BaseModelBackendTest(object):
|
| 111 | 126 | user = self.UserModel._default_manager.get(pk=self.superuser.pk) |
| 112 | 127 | self.assertEqual(len(user.get_all_permissions()), len(Permission.objects.all())) |
| 113 | 128 | |
| | 129 | @override_settings(PASSWORD_HASHERS=('django.contrib.auth.tests.test_auth_backends.MockHasher',)) |
| | 130 | def test_authentication_timing(self): |
| | 131 | """ |
| | 132 | Tests that the hasher is run the same number of times whether a user exists or not |
| | 133 | |
| | 134 | Refs #20760 |
| | 135 | """ |
| | 136 | #ensures the proper natural key is passed in custom models |
| | 137 | kwargs = {self.UserModel.USERNAME_FIELD : self.UserModel._default_manager.get(pk=1).natural_key()[0]} |
| | 138 | authenticate(password='test', **kwargs) |
| | 139 | exists = MockHasher.hash_count |
| | 140 | |
| | 141 | MockHasher.hash_count = 0 |
| | 142 | |
| | 143 | #don't use these creds in a test account |
| | 144 | kwargs = {self.UserModel.USERNAME_FIELD : 'paglierani'} |
| | 145 | authenticate(password='justin', **kwargs) |
| | 146 | dne = MockHasher.hash_count |
| | 147 | self.assertEqual(exists, dne) #counts should be the same |
| | 148 | |
| 114 | 149 | |
| 115 | 150 | @skipIfCustomUser |
| 116 | 151 | class ModelBackendTest(BaseModelBackendTest, TestCase): |