moved a config out of middleware into config and also updated README

This commit is contained in:
Ken Cochrane 2015-01-03 10:34:19 -05:00
parent 271fde9dae
commit 7e32eacd97
4 changed files with 27 additions and 29 deletions

View file

@ -16,9 +16,7 @@ the goal is to do those things very well, and have full unit tests with docs.
Build status
------------
[![Build Status](https://travis-ci.org/kencochrane/django-defender.svg)](https://travis-ci.org/kencochrane/django-defender)
[![Coverage Status](https://img.shields.io/coveralls/kencochrane/django-defender.svg)](https://coveralls.io/r/kencochrane/django-defender)
[![Build Status](https://travis-ci.org/kencochrane/django-defender.svg)](https://travis-ci.org/kencochrane/django-defender) [![Coverage Status](https://img.shields.io/coveralls/kencochrane/django-defender.svg)](https://coveralls.io/r/kencochrane/django-defender)
Goals for 0.1
=============
@ -105,10 +103,10 @@ destination.
Cache backend:
==============
- IP_attempts (count, TTL)
- ip_attempts (count, TTL)
- username_attempts (count, TTL)
- ip_blocks (list) # how to expire when in a list?
- username_blocks (list) # how to expire item in the list?
- ip_blocks (list)
- username_blocks (list)
cache keys:
-----------
@ -192,29 +190,30 @@ Customizing Defender
You have a couple options available to you to customize ``django-defender`` a bit.
These should be defined in your ``settings.py`` file.
* ``DEFENDER_LOGIN_FAILURE_LIMIT``: The number of login attempts allowed before a
* ``DEFENDER_LOGIN_FAILURE_LIMIT``: Int: The number of login attempts allowed before a
record is created for the failed logins. Default: ``3``
* ``DEFENDER_USE_USER_AGENT``: If ``True``, lock out / log based on an IP address
* ``DEFENDER_USE_USER_AGENT``: Boolean: If ``True``, lock out / log based on an IP address
AND a user agent. This means requests from different user agents but from
the same IP are treated differently. Default: ``False``
* ``DEFENDER_COOLOFF_TIME``: If set, defines a period of inactivity after which
* ``DEFENDER_COOLOFF_TIME``: Int: If set, defines a period of inactivity after which
old failed login attempts will be forgotten. An integer, will be interpreted as a
number of seconds. If ``0``, the locks will not expire. Default: ``300``
* ``DEFENDER_LOCKOUT_TEMPLATE``: If set, specifies a template to render when a
* ``DEFENDER_LOCKOUT_TEMPLATE``: String: If set, specifies a template to render when a
user is locked out. Template receives cooloff_time and failure_limit as
context variables. Default: ``None``
* ``DEFENDER_USERNAME_FORM_FIELD``: the name of the form field that contains your
* ``DEFENDER_USERNAME_FORM_FIELD``: String: the name of the form field that contains your
users usernames. Default: ``username``
* ``DEFENDER_REVERSE_PROXY_HEADER``: the name of the http header with your
* ``DEFENDER_REVERSE_PROXY_HEADER``: String: the name of the http header with your
reverse proxy IP address Default: ``HTTP_X_FORWARDED_FOR``
* ``DEFENDER_CACHE_PREFIX``: The cache prefix for your defender keys.
* ``DEFENDER_CACHE_PREFIX``: String: The cache prefix for your defender keys.
Default: ``defender``
* ``DEFENDER_LOCKOUT_URL``: The URL you want to redirect to if someone is
* ``DEFENDER_LOCKOUT_URL``: String: The URL you want to redirect to if someone is
locked out.
* ``DEFENDER_REDIS_URL``: the redis url for defender.
* ``DEFENDER_REDIS_URL``: String: the redis url for defender.
Default: ``redis://localhost:6379/0``
(Example with password: ``redis://:mypassword@localhost:6379/0``)
* ``DEFENDER_PROTECTED_LOGINS``: Tuple: Used by ``ViewDecoratorMiddleware`` to decide
which login urls need protecting. Default: ``('/accounts/login/',)``
Running Tests
=============

View file

@ -46,3 +46,7 @@ ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. "
USERNAME_FORM_FIELD = get_setting('DEFENDER_USERNAME_FORM_FIELD', 'username')
LOCKOUT_URL = get_setting('DEFENDER_LOCKOUT_URL')
PROTECTED_LOGINS = get_setting('DEFENDER_PROTECTED_LOGINS',
('/accounts/login/',))

View file

@ -1,7 +1,7 @@
from django.conf import settings
from django.contrib.auth import views as auth_views
from .decorators import watch_login
from .config import PROTECTED_LOGINS
class FailedLoginMiddleware(object):
@ -22,14 +22,8 @@ class ViewDecoratorMiddleware(object):
`defender.middleware.FailedLoginMiddleware` and before the django
flatpages middleware.
"""
watched_logins = getattr(
settings, 'DEFENDER_PROTECTED_LOGINS', (
'/accounts/login/',
)
)
def process_view(self, request, view_func, view_args, view_kwargs):
if request.path in self.watched_logins:
if request.path in PROTECTED_LOGINS:
return watch_login(view_func)(request, *view_args, **view_kwargs)
return None

View file

@ -444,15 +444,16 @@ class AccessAttemptTest(TestCase):
from .admin import AccessAttemptAdmin
AccessAttemptAdmin
@patch('defender.middleware.ViewDecoratorMiddleware.watched_logins',
(ADMIN_LOGIN_URL, ))
@patch('defender.config.PROTECTED_LOGINS', (ADMIN_LOGIN_URL, ))
def test_decorator_middleware(self):
# because watch_login is called twice in this test (once by the
# middleware and once by the decorator) we have half as many attempts
# before getting locked out.
# FIXME: I tried making sure every request in only processed once but
# there seems to be an issue with django reusing request objects.
for i in range(0, int(config.FAILURE_LIMIT / 2)):
# this is getting called twice, once for each decorator, not sure how
# to dynamically remove one of the middlewares during a test so we
# divide the failure limit by 2.
for i in range(0, int(config.FAILURE_LIMIT)):
response = self._login()
# Check if we are in the same login page
self.assertContains(response, LOGIN_FORM_KEY)