Ejemplo n.º 1
0
    def test_expiry(self):
        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req, data={
            'username': '******', 'password': '******'})
        self.assertTrue(form.is_valid())

        # Simulate user didn't log in for a long time
        period = datetime.timedelta(days=dap_settings.INACTIVE_USERS_EXPIRY)
        expire_at = timezone.now() - period
        self.user.last_login = expire_at
        self.user.save()
        LoginAttempt.objects.all().update(timestamp=expire_at)

        # Login attempt disabled user
        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req, data={
            'username': '******', 'password': '******'})
        self.assertFalse(form.is_valid())
        self.assertEqual(form.non_field_errors(), [
            form.error_messages['inactive']])

        # Check log messages
        self.assertEqual(self.logger.handlers[0].stream.getvalue(), (
            u'INFO Authentication attempt, username=rf, address=127.0.0.1\n'
            u'INFO Authentication success, username=rf, address=127.0.0.1\n'
            u'INFO Authentication attempt, username=rf, address=127.0.0.1\n'
            u'WARNING User rf disabled because last login was at %s\n'
            u'WARNING Authentication failure, username=rf, address=127.0.0.1, '
            u'user inactive.\n' % expire_at))
Ejemplo n.º 2
0
    def test_lock_period(self):
        for x in xrange(0, dap_settings.FAILED_AUTH_USERNAME_MAX + 1):

            req = self.factory.get(reverse('login'))

            form = StrictAuthenticationForm(request=req, data={
                'username': '******', 'password': '******'})

            self.assertFalse(form.is_valid())

        # User locked out
        self.assertEqual(form.non_field_errors(), [
            form.error_messages['username_locked_out']])

        # Alter timestamps as if they happened longer ago
        period = datetime.timedelta(
            seconds=dap_settings.FAILED_AUTH_LOCKOUT_PERIOD)
        expire_at = timezone.now() - period
        LoginAttempt.objects.all().update(timestamp=expire_at)

        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req, data={
            'username': '******', 'password': '******'})
        self.assertTrue(form.is_valid())

        # Successful login resets lock count
        locking_attempts = LoginAttempt.objects.filter(lockout=True)
        self.assertEqual(locking_attempts.count(), 0)
Ejemplo n.º 3
0
    def test_lock_period(self):
        pol = AuthenticationLockedUsername()
        text = unicode(pol.validation_msg)
        for x in xrange(0, pol.max_failed + 1):

            req = self.factory.get(reverse('login'))

            form = StrictAuthenticationForm(request=req, data={
                'username': '******', 'password': '******'})

            self.assertFalse(form.is_valid())

        # User locked out
        self.assertEqual(form.non_field_errors(), [text])

        # Alter timestamps as if they happened longer ago
        period = datetime.timedelta(seconds=pol.lockout_duration)
        expire_at = timezone.now() - period
        LoginAttempt.objects.all().update(timestamp=expire_at)

        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req, data={
            'username': '******', 'password': '******'})
        self.assertTrue(form.is_valid())

        # Successful login resets lock count
        locking_attempts = LoginAttempt.objects.filter(lockout=True)
        self.assertEqual(locking_attempts.count(), 0)
Ejemplo n.º 4
0
    def test_username_lockout(self):
        """ Test too many failed login attempts for one username """
        pol = AuthenticationLockedUsername()
        text = str(pol.validation_msg)
        for x in xrange(0, pol.max_failed):

            self.assertFalse(self.lockout_policy.is_locked('rf'))

            req = self.factory.get(reverse('login'))
            req.META['REMOTE_ADDR'] = '10.0.0.%d' % (x + 1)

            form = StrictAuthenticationForm(request=req, data={
                'username': '******', 'password': '******'})

            self.assertEqual(form.non_field_errors(), [
                form.error_messages['invalid_login'] % {
                    'username': form.username_field.verbose_name}]
            )

        attempts = LoginAttempt.objects.filter(username=self.user.username,
                                               successful=False, lockout=True)

        self.assertEqual(attempts.count(),
                         pol.max_failed)

        self.assertTrue(self.lockout_policy.is_locked('rf'))

        # Another failed authentication triggers lockout
        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req, data={
            'username': '******', 'password': '******'})
        self.assertEqual(form.non_field_errors(), [text])

        self.assertEqual(attempts.count(),
                         pol.max_failed + 1)

        # Even valid authentication will no longer work now
        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req, data={
            'username': '******', 'password': '******'})
        self.assertFalse(form.is_valid())

        self.assertEqual(self.logger.handlers[0].stream.getvalue(), (
            u'INFO Authentication attempt, username=rf, address=10.0.0.1\n'
            u'INFO Authentication failure, username=rf, address=10.0.0.1, '
            u'invalid authentication.\n'
            u'INFO Authentication attempt, username=rf, address=10.0.0.2\n'
            u'INFO Authentication failure, username=rf, address=10.0.0.2, '
            u'invalid authentication.\n'
            u'INFO Authentication attempt, username=rf, address=10.0.0.3\n'
            u'INFO Authentication failure, username=rf, address=10.0.0.3, '
            u'invalid authentication.\n'
            u'INFO Authentication attempt, username=rf, address=127.0.0.1\n'
            u'INFO Authentication failure, username=rf, address=127.0.0.1, '
            u'username locked\n'
            u'INFO Authentication attempt, username=rf, address=127.0.0.1\n'
            u'INFO Authentication failure, username=rf, address=127.0.0.1, '
            u'username locked\n'))
Ejemplo n.º 5
0
    def test_backend_locked_username(self):
        # Authentication works
        backend = StrictModelBackend()
        user = backend.authenticate(username='******', password='******')
        self.assertEqual(user, self.user)

        # Lock user
        for x in xrange(0, dap_settings.FAILED_AUTH_USERNAME_MAX + 1):
            req = self.factory.get(reverse('login'))
            form = StrictAuthenticationForm(request=req, data={
                'username': '******', 'password': '******'})
            self.assertFalse(form.is_valid())

        # Authentication must no longer work for this user
        user = backend.authenticate(username='******', password='******')
        self.assertEqual(user, None)
Ejemplo n.º 6
0
    def test_inactive_user(self):
        self.user.is_active = False
        self.user.save()

        # Valid authentication data, but user is inactive
        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req, data={
            'username': '******', 'password': '******'})
        self.assertFalse(form.is_valid())
        self.assertEqual(form.non_field_errors(), [
            form.error_messages['inactive']])

        self.assertEqual(self.logger.handlers[0].stream.getvalue(), (
            u'INFO Authentication attempt, username=rf, address=127.0.0.1\n'
            u'WARNING Authentication failure, username=rf, address=127.0.0.1, '
            u'user inactive.\n'))
Ejemplo n.º 7
0
    def test_address_lockout(self):
        """ Test too many failed login attempts for one address """

        addr = '1.2.3.4'

        for x in xrange(0, dap_settings.FAILED_AUTH_ADDRESS_MAX):

            req = self.factory.get(reverse('login'))
            req.META['REMOTE_ADDR'] = addr

            form = StrictAuthenticationForm(request=req, data={
                'username': '******' % x, 'password': '******'})

            self.assertEqual(form.non_field_errors(), [
                form.error_messages['invalid_login'] % {
                    'username': form.username_field.verbose_name}])

        attempts = LoginAttempt.objects.filter(source_address=addr,
                                               successful=False, lockout=True)

        self.assertEqual(attempts.count(),
                         dap_settings.FAILED_AUTH_ADDRESS_MAX)

        # Another failed authentication triggers lockout
        req = self.factory.get(reverse('login'))
        req.META['REMOTE_ADDR'] = addr
        form = StrictAuthenticationForm(request=req, data={
            'username': '******', 'password': '******'})
        self.assertEqual(form.non_field_errors(), [
            form.error_messages['address_locked_out']])

        self.assertEqual(attempts.count(),
                         dap_settings.FAILED_AUTH_ADDRESS_MAX + 1)

        self.assertEqual(self.logger.handlers[0].stream.getvalue(), (
            u'INFO Authentication attempt, username=rf0, address=1.2.3.4\n'
            u'WARNING Authentication failure, username=rf0, address=1.2.3.4, '
            u'invalid authentication.\n'
            u'INFO Authentication attempt, username=rf1, address=1.2.3.4\n'
            u'WARNING Authentication failure, username=rf1, address=1.2.3.4, '
            u'invalid authentication.\n'
            u'INFO Authentication attempt, username=rf2, address=1.2.3.4\n'
            u'WARNING Authentication failure, username=rf2, address=1.2.3.4, '
            u'invalid authentication.\n'
            u'INFO Authentication attempt, username=rf, address=1.2.3.4\n'
            u'WARNING Authentication failure, username=rf, address=1.2.3.4, '
            u'address locked\n'))
Ejemplo n.º 8
0
    def test_lock_period(self):
        for x in xrange(0, dap_settings.FAILED_AUTH_USERNAME_MAX + 1):

            req = self.factory.get(reverse('login'))

            form = StrictAuthenticationForm(request=req,
                                            data={
                                                'username': '******',
                                                'password': '******'
                                            })

            self.assertFalse(form.is_valid())

        # User locked out
        self.assertEqual(form.non_field_errors(),
                         [form.error_messages['username_locked_out']])

        # Alter timestamps as if they happened longer ago
        period = datetime.timedelta(
            seconds=dap_settings.FAILED_AUTH_LOCKOUT_PERIOD)
        expire_at = timezone.now() - period
        LoginAttempt.objects.all().update(timestamp=expire_at)

        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req,
                                        data={
                                            'username': '******',
                                            'password': '******'
                                        })
        self.assertTrue(form.is_valid())

        # Successful login resets lock count
        locking_attempts = LoginAttempt.objects.filter(lockout=True)
        self.assertEqual(locking_attempts.count(), 0)
Ejemplo n.º 9
0
    def test_lock_period(self):
        pol = AuthenticationLockedUsername()
        text = unicode(pol.validation_msg)
        for x in xrange(0, pol.max_failed + 1):

            req = self.factory.get(reverse('login'))

            form = StrictAuthenticationForm(request=req,
                                            data={
                                                'username': '******',
                                                'password': '******'
                                            })

            self.assertFalse(form.is_valid())

        # User locked out
        self.assertEqual(form.non_field_errors(), [text])

        # Alter timestamps as if they happened longer ago
        period = datetime.timedelta(seconds=pol.lockout_duration)
        expire_at = timezone.now() - period
        LoginAttempt.objects.all().update(timestamp=expire_at)

        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req,
                                        data={
                                            'username': '******',
                                            'password': '******'
                                        })
        self.assertTrue(form.is_valid())

        # Successful login resets lock count
        locking_attempts = LoginAttempt.objects.filter(lockout=True)
        self.assertEqual(locking_attempts.count(), 0)
Ejemplo n.º 10
0
    def test_expiry(self):
        pol = AuthenticationDisableExpiredUsers()

        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req, data={
            'username': '******', 'password': '******'})
        self.assertTrue(form.is_valid())

        # Simulate user didn't log in for a long time
        period = datetime.timedelta(days=pol.inactive_period)
        expire_at = timezone.now() - period
        self.user.last_login = expire_at
        self.user.save()
        LoginAttempt.objects.all().update(timestamp=expire_at)

        # Login attempt disabled user
        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req, data={
            'username': '******', 'password': '******'})
        self.assertFalse(form.is_valid())
        self.assertEqual(form.non_field_errors(), [
            form.error_messages['invalid_login'] % {
                'username': form.username_field.verbose_name
            }]
        )

        # Check log messages
        self.assertEqual(self.logger.handlers[0].stream.getvalue(), (
            u'INFO Authentication attempt, username=rf, address=127.0.0.1\n'
            u'INFO Authentication success, username=rf, address=127.0.0.1\n'
            u'INFO Authentication attempt, username=rf, address=127.0.0.1\n'
            u'INFO User rf disabled because last login was at %s\n'
            u'INFO Authentication failure, username=rf, address=127.0.0.1, '
            u'user inactive.\n' % expire_at))
Ejemplo n.º 11
0
    def test_unlock(self):
        """ Resetting lockout data unlocks user """
        for x in xrange(0, dap_settings.FAILED_AUTH_USERNAME_MAX + 1):

            req = self.factory.get(reverse('login'))

            form = StrictAuthenticationForm(request=req,
                                            data={
                                                'username': '******',
                                                'password': '******'
                                            })

            self.assertFalse(form.is_valid())

        # User locked out
        self.assertEqual(form.non_field_errors(),
                         [form.error_messages['username_locked_out']])

        # Unlock user or address
        LoginAttempt.objects.all().update(lockout=False)

        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req,
                                        data={
                                            'username': '******',
                                            'password': '******'
                                        })
        self.assertTrue(form.is_valid())
Ejemplo n.º 12
0
    def test_unlock(self):
        """ Resetting lockout data unlocks user """
        pol = AuthenticationLockedUsername()
        text = unicode(pol.validation_msg)
        for x in xrange(0, pol.max_failed + 1):

            req = self.factory.get(reverse('login'))

            form = StrictAuthenticationForm(request=req,
                                            data={
                                                'username': '******',
                                                'password': '******'
                                            })

            self.assertFalse(form.is_valid())

        # User locked out
        self.assertEqual(form.non_field_errors(), [text])

        # Unlock user or address
        LoginAttempt.objects.all().update(lockout=False)

        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req,
                                        data={
                                            'username': '******',
                                            'password': '******'
                                        })
        self.assertTrue(form.is_valid())
Ejemplo n.º 13
0
    def test_backend_locked_username(self):
        # Authentication works
        backend = StrictModelBackend()
        user = backend.authenticate(username='******', password='******')
        self.assertEqual(user, self.user)

        # Lock user
        for x in xrange(0, dap_settings.FAILED_AUTH_USERNAME_MAX + 1):
            req = self.factory.get(reverse('login'))
            form = StrictAuthenticationForm(request=req,
                                            data={
                                                'username': '******',
                                                'password': '******'
                                            })
            self.assertFalse(form.is_valid())

        # Authentication must no longer work for this user
        user = backend.authenticate(username='******', password='******')
        self.assertEqual(user, None)
Ejemplo n.º 14
0
    def test_inactive_user(self):
        self.user.is_active = False
        self.user.save()

        # Valid authentication data, but user is inactive
        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req, data={
            'username': '******', 'password': '******'})
        self.assertFalse(form.is_valid())
        self.assertEqual(form.non_field_errors(), [
            form.error_messages['invalid_login'] % {
                'username': form.username_field.verbose_name
            }]
        )

        self.assertEqual(self.logger.handlers[0].stream.getvalue(), (
            u'INFO Authentication attempt, username=rf, address=127.0.0.1\n'
            u'INFO Authentication failure, username=rf, address=127.0.0.1, '
            u'user inactive.\n'))
Ejemplo n.º 15
0
    def test_unlock(self):
        """ Resetting lockout data unlocks user """
        for x in xrange(0, dap_settings.FAILED_AUTH_USERNAME_MAX + 1):

            req = self.factory.get(reverse('login'))

            form = StrictAuthenticationForm(request=req, data={
                'username': '******', 'password': '******'})

            self.assertFalse(form.is_valid())

        # User locked out
        self.assertEqual(form.non_field_errors(), [
            form.error_messages['username_locked_out']])

        # Unlock user or address
        LoginAttempt.objects.all().update(lockout=False)

        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req, data={
            'username': '******', 'password': '******'})
        self.assertTrue(form.is_valid())
Ejemplo n.º 16
0
    def test_username_lockout(self):
        """ Test too many failed login attempts for one username """
        pol = AuthenticationLockedUsername()
        text = unicode(pol.validation_msg)
        for x in xrange(0, pol.max_failed):

            self.assertFalse(self.lockout_policy.is_locked('rf'))

            req = self.factory.get(reverse('login'))
            req.META['REMOTE_ADDR'] = '10.0.0.%d' % (x + 1)

            form = StrictAuthenticationForm(request=req, data={
                'username': '******', 'password': '******'})

            self.assertEqual(form.non_field_errors(), [
                form.error_messages['invalid_login'] % {
                    'username': form.username_field.verbose_name}]
            )

        attempts = LoginAttempt.objects.filter(username=self.user.username,
                                               successful=False, lockout=True)

        self.assertEqual(attempts.count(),
                         pol.max_failed)

        self.assertTrue(self.lockout_policy.is_locked('rf'))

        # Another failed authentication triggers lockout
        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req, data={
            'username': '******', 'password': '******'})
        self.assertEqual(form.non_field_errors(), [text])

        self.assertEqual(attempts.count(),
                         pol.max_failed + 1)

        # Even valid authentication will no longer work now
        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req, data={
            'username': '******', 'password': '******'})
        self.assertFalse(form.is_valid())

        self.assertEqual(self.logger.handlers[0].stream.getvalue(), (
            u'INFO Authentication attempt, username=rf, address=10.0.0.1\n'
            u'INFO Authentication failure, username=rf, address=10.0.0.1, '
            u'invalid authentication.\n'
            u'INFO Authentication attempt, username=rf, address=10.0.0.2\n'
            u'INFO Authentication failure, username=rf, address=10.0.0.2, '
            u'invalid authentication.\n'
            u'INFO Authentication attempt, username=rf, address=10.0.0.3\n'
            u'INFO Authentication failure, username=rf, address=10.0.0.3, '
            u'invalid authentication.\n'
            u'INFO Authentication attempt, username=rf, address=127.0.0.1\n'
            u'INFO Authentication failure, username=rf, address=127.0.0.1, '
            u'username locked\n'
            u'INFO Authentication attempt, username=rf, address=127.0.0.1\n'
            u'INFO Authentication failure, username=rf, address=127.0.0.1, '
            u'username locked\n'))
Ejemplo n.º 17
0
    def test_unlock(self):
        """ Resetting lockout data unlocks user """
        pol = AuthenticationLockedUsername()
        text = unicode(pol.validation_msg)
        for x in xrange(0, pol.max_failed + 1):

            req = self.factory.get(reverse('login'))

            form = StrictAuthenticationForm(request=req, data={
                'username': '******', 'password': '******'})

            self.assertFalse(form.is_valid())

        # User locked out
        self.assertEqual(form.non_field_errors(), [text])

        # Unlock user or address
        LoginAttempt.objects.all().update(lockout=False)

        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req, data={
            'username': '******', 'password': '******'})
        self.assertTrue(form.is_valid())
Ejemplo n.º 18
0
    def test_address_lockout(self):
        """ Test too many failed login attempts for one address """

        addr = '1.2.3.4'

        for x in xrange(0, dap_settings.FAILED_AUTH_ADDRESS_MAX):

            req = self.factory.get(reverse('login'))
            req.META['REMOTE_ADDR'] = addr

            form = StrictAuthenticationForm(request=req,
                                            data={
                                                'username': '******' % x,
                                                'password': '******'
                                            })

            self.assertEqual(form.non_field_errors(), [
                form.error_messages['invalid_login'] % {
                    'username': form.username_field.verbose_name
                }
            ])

        attempts = LoginAttempt.objects.filter(source_address=addr,
                                               successful=False,
                                               lockout=True)

        self.assertEqual(attempts.count(),
                         dap_settings.FAILED_AUTH_ADDRESS_MAX)

        # Another failed authentication triggers lockout
        req = self.factory.get(reverse('login'))
        req.META['REMOTE_ADDR'] = addr
        form = StrictAuthenticationForm(request=req,
                                        data={
                                            'username': '******',
                                            'password': '******'
                                        })
        self.assertEqual(form.non_field_errors(),
                         [form.error_messages['address_locked_out']])

        self.assertEqual(attempts.count(),
                         dap_settings.FAILED_AUTH_ADDRESS_MAX + 1)

        self.assertEqual(
            self.logger.handlers[0].stream.getvalue(),
            (u'INFO Authentication attempt, username=rf0, address=1.2.3.4\n'
             u'WARNING Authentication failure, username=rf0, address=1.2.3.4, '
             u'invalid authentication.\n'
             u'INFO Authentication attempt, username=rf1, address=1.2.3.4\n'
             u'WARNING Authentication failure, username=rf1, address=1.2.3.4, '
             u'invalid authentication.\n'
             u'INFO Authentication attempt, username=rf2, address=1.2.3.4\n'
             u'WARNING Authentication failure, username=rf2, address=1.2.3.4, '
             u'invalid authentication.\n'
             u'INFO Authentication attempt, username=rf, address=1.2.3.4\n'
             u'WARNING Authentication failure, username=rf, address=1.2.3.4, '
             u'address locked\n'))
Ejemplo n.º 19
0
    def test_username_lockout(self):
        """ Test too many failed login attempts for one username """

        for x in xrange(0, dap_settings.FAILED_AUTH_USERNAME_MAX):

            req = self.factory.get(reverse('login'))
            req.META['REMOTE_ADDR'] = '10.0.0.%d' % (x + 1)

            form = StrictAuthenticationForm(request=req, data={
                'username': '******', 'password': '******'})

            self.assertEqual(form.non_field_errors(), [
                form.error_messages['invalid_login'] % {
                    'username': form.username_field.verbose_name}])

        attempts = LoginAttempt.objects.filter(username=self.user.username,
                                               successful=False, lockout=True)

        self.assertEqual(attempts.count(),
                         dap_settings.FAILED_AUTH_USERNAME_MAX)

        # Another failed authentication triggers lockout
        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req, data={
            'username': '******', 'password': '******'})
        self.assertEqual(form.non_field_errors(), [
            form.error_messages['username_locked_out']])

        self.assertEqual(attempts.count(),
                         dap_settings.FAILED_AUTH_USERNAME_MAX + 1)

        # Even valid authentication will no longer work now
        req = self.factory.get(reverse('login'))
        form = StrictAuthenticationForm(request=req, data={
            'username': '******', 'password': '******'})
        self.assertFalse(form.is_valid())

        self.assertEqual(self.logger.handlers[0].stream.getvalue(), (
            u'INFO Authentication attempt, username=rf, address=10.0.0.1\n'
            u'WARNING Authentication failure, username=rf, address=10.0.0.1, '
            u'invalid authentication.\n'
            u'INFO Authentication attempt, username=rf, address=10.0.0.2\n'
            u'WARNING Authentication failure, username=rf, address=10.0.0.2, '
            u'invalid authentication.\n'
            u'INFO Authentication attempt, username=rf, address=10.0.0.3\n'
            u'WARNING Authentication failure, username=rf, address=10.0.0.3, '
            u'invalid authentication.\n'
            u'INFO Authentication attempt, username=rf, address=127.0.0.1\n'
            u'WARNING Authentication failure, username=rf, address=127.0.0.1, '
            u'username locked\n'
            u'INFO Authentication attempt, username=rf, address=127.0.0.1\n'
            u'WARNING Authentication failure, username=rf, address=127.0.0.1, '
            u'username locked\n'))
Ejemplo n.º 20
0
    def test_address_lockout(self):
        """ Test too many failed login attempts for one address """
        pol = AuthenticationLockedRemoteAddress()
        text = str(pol.validation_msg)

        addr = '1.2.3.4'

        for x in range(0, pol.max_failed):

            req = self.factory.get(reverse('login'))
            req.META['REMOTE_ADDR'] = addr

            form = StrictAuthenticationForm(request=req, data={
                'username': '******' % x, 'password': '******'})

            self.assertEqual(form.non_field_errors(), [
                form.error_messages['invalid_login'] % {
                    'username': form.username_field.verbose_name}]
            )

        attempts = LoginAttempt.objects.filter(source_address=addr,
                                               successful=False, lockout=True)

        self.assertEqual(attempts.count(), pol.max_failed)

        # Another failed authentication triggers lockout
        req = self.factory.get(reverse('login'))
        req.META['REMOTE_ADDR'] = addr
        form = StrictAuthenticationForm(request=req, data={
            'username': '******', 'password': '******'})
        self.assertEqual(form.non_field_errors(), [text])

        self.assertEqual(attempts.count(), pol.max_failed + 1)

        self.assertEqual(self.logger.handlers[0].stream.getvalue(), (
            'INFO Authentication attempt, username=rf0, address=1.2.3.4\n'
            'INFO Authentication failure, username=rf0, address=1.2.3.4, '
            'invalid authentication.\n'
            'INFO Authentication attempt, username=rf1, address=1.2.3.4\n'
            'INFO Authentication failure, username=rf1, address=1.2.3.4, '
            'invalid authentication.\n'
            'INFO Authentication attempt, username=rf2, address=1.2.3.4\n'
            'INFO Authentication failure, username=rf2, address=1.2.3.4, '
            'invalid authentication.\n'
            'INFO Authentication attempt, username=rf, address=1.2.3.4\n'
            'INFO Authentication failure, username=rf, address=1.2.3.4, '
            'address locked\n'))