diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py
index 029193d..53aa4b3 100644
a
|
b
|
|
1 | 1 | import re |
| 2 | import logging |
2 | 3 | |
3 | 4 | from django.conf import settings |
4 | 5 | from django.core.exceptions import ImproperlyConfigured, PermissionDenied |
… |
… |
SESSION_KEY = '_auth_user_id'
|
11 | 12 | BACKEND_SESSION_KEY = '_auth_user_backend' |
12 | 13 | REDIRECT_FIELD_NAME = 'next' |
13 | 14 | |
| 15 | logger = logging.getLogger('django.security') |
14 | 16 | |
15 | 17 | def load_backend(path): |
16 | 18 | return import_by_path(path)() |
… |
… |
def authenticate(**credentials):
|
59 | 61 | user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) |
60 | 62 | return user |
61 | 63 | |
62 | | # The credentials supplied are invalid to all backends, fire signal |
63 | | user_login_failed.send(sender=__name__, |
64 | | credentials=_clean_credentials(credentials)) |
| 64 | # The credentials supplied are invalid to all backends, log error |
| 65 | logger.error(("user login failed: %s" % credentials['username'])) |
65 | 66 | |
66 | 67 | |
67 | 68 | def login(request, user): |
diff --git a/django/contrib/auth/tests/test_signals.py b/django/contrib/auth/tests/test_signals.py
index 024f44f..b3d8b20 100644
a
|
b
|
class SignalTestCase(TestCase):
|
40 | 40 | # Only a successful login will trigger the success signal. |
41 | 41 | self.client.login(username='testclient', password='bad') |
42 | 42 | self.assertEqual(len(self.logged_in), 0) |
43 | | self.assertEqual(len(self.login_failed), 1) |
44 | | self.assertEqual(self.login_failed[0]['username'], 'testclient') |
45 | | # verify the password is cleansed |
46 | | self.assertTrue('***' in self.login_failed[0]['password']) |
47 | 43 | |
48 | 44 | # Like this: |
49 | 45 | self.client.login(username='testclient', password='password') |
50 | 46 | self.assertEqual(len(self.logged_in), 1) |
51 | 47 | self.assertEqual(self.logged_in[0].username, 'testclient') |
52 | 48 | |
53 | | # Ensure there were no more failures. |
54 | | self.assertEqual(len(self.login_failed), 1) |
55 | | |
56 | 49 | def test_logout_anonymous(self): |
57 | 50 | # The log_out function will still trigger the signal for anonymous |
58 | 51 | # users. |
diff --git a/tests/logging_tests/tests.py b/tests/logging_tests/tests.py
index 0c2d269..1a2bf75 100644
a
|
b
|
class SecurityLoggerTest(TestCase):
|
374 | 374 | response = self.client.get('/suspicious_spec/') |
375 | 375 | self.assertEqual(len(calls), 1) |
376 | 376 | self.assertEqual(calls[0], 'dubious') |
| 377 | |
| 378 | def test_user_login_failed_creates_log_message(self): |
| 379 | with self.settings(DEBUG=True): |
| 380 | with patch_logger('django.security', 'error') as calls: |
| 381 | self.client.login(username='testclient', password='bad') |
| 382 | self.assertEqual(len(calls), 1) |
| 383 | self.assertEqual(calls[0], "user login failed: testclient") |