Fixed #18171 -- Checked signature of authenticate() to avoid supressing TypeErrors.
The current auth backend code catches TypeError to detect backends that do not support specified argumetnts. As a result, any TypeErrors raised within the actual backend code are silenced. In Python 2.7+ and 3.2+ this can be avoided by using inspect.getcallargs(). With this method, we can test whether arguments match the signature without actually calling the function. Thanks David Eyk for the report.
This commit is contained in:
parent
5b889b2408
commit
b89c2a5d9e
|
@ -1,3 +1,4 @@
|
|||
import inspect
|
||||
import re
|
||||
|
||||
from django.conf import settings
|
||||
|
@ -46,10 +47,13 @@ def authenticate(**credentials):
|
|||
"""
|
||||
for backend in get_backends():
|
||||
try:
|
||||
user = backend.authenticate(**credentials)
|
||||
inspect.getcallargs(backend.authenticate, **credentials)
|
||||
except TypeError:
|
||||
# This backend doesn't accept these credentials as arguments. Try the next one.
|
||||
continue
|
||||
|
||||
try:
|
||||
user = backend.authenticate(**credentials)
|
||||
except PermissionDenied:
|
||||
# This backend says to stop in our tracks - this user should not be allowed in at all.
|
||||
return None
|
||||
|
|
|
@ -480,3 +480,32 @@ class ChangedBackendSettingsTest(TestCase):
|
|||
# anonymous as the backend is not longer available.
|
||||
self.assertIsNotNone(user)
|
||||
self.assertTrue(user.is_anonymous())
|
||||
|
||||
|
||||
class TypeErrorBackend(object):
|
||||
"""
|
||||
Always raises TypeError.
|
||||
"""
|
||||
supports_object_permissions = True
|
||||
supports_anonymous_user = True
|
||||
supports_inactive_user = True
|
||||
|
||||
def authenticate(self, username=None, password=None):
|
||||
raise TypeError
|
||||
|
||||
|
||||
@skipIfCustomUser
|
||||
class TypeErrorBackendTest(TestCase):
|
||||
"""
|
||||
Tests that a TypeError within a backend is propagated properly.
|
||||
|
||||
Regression test for ticket #18171
|
||||
"""
|
||||
backend = 'django.contrib.auth.tests.test_auth_backends.TypeErrorBackend'
|
||||
|
||||
def setUp(self):
|
||||
self.user1 = User.objects.create_user('test', 'test@example.com', 'test')
|
||||
|
||||
@override_settings(AUTHENTICATION_BACKENDS=(backend, ))
|
||||
def test_type_error_raised(self):
|
||||
self.assertRaises(TypeError, authenticate, username='test', password='test')
|
||||
|
|
Loading…
Reference in New Issue