mirror of
https://github.com/jazzband/django-defender.git
synced 2026-05-04 21:54:53 +00:00
fixed issues #15 #35 and #36, added way to clean up access attempt table, as well as an option to not login attempts. Also speed up django admin pages
This commit is contained in:
parent
231db4a633
commit
47d6a71825
6 changed files with 68 additions and 13 deletions
|
|
@ -8,8 +8,8 @@ python:
|
|||
- "pypy"
|
||||
|
||||
env:
|
||||
- DJANGO=Django==1.6.10
|
||||
- DJANGO=Django==1.7.5
|
||||
- DJANGO=Django==1.6.11
|
||||
- DJANGO=Django==1.7.7
|
||||
|
||||
services:
|
||||
- redis-server
|
||||
|
|
@ -28,7 +28,7 @@ script:
|
|||
matrix:
|
||||
exclude:
|
||||
- python: "2.6"
|
||||
env: DJANGO=Django==1.7.5
|
||||
env: DJANGO=Django==1.7.7
|
||||
|
||||
after_success:
|
||||
- coveralls --verbose
|
||||
|
|
|
|||
43
README.md
43
README.md
|
|
@ -22,6 +22,16 @@ Sites using Defender:
|
|||
|
||||
Versions
|
||||
========
|
||||
- 0.3
|
||||
- Added management command ``cleanup_django_axes`` to clean up access
|
||||
attempt table.
|
||||
- Added ``DEFENDER_STORE_ACCESS_ATTEMPTS`` config to say if you want to
|
||||
store attempts to DB or not.
|
||||
- Added ``DEFENDER_ACCESS_ATTEMPT_EXPIRATION`` config to specify how long
|
||||
to store the access attempt records in the db, before the management command
|
||||
cleans them up.
|
||||
- changed the Django admin page to remove some filters which were making the
|
||||
page load slow with lots of login attempts in the database.
|
||||
- 0.2.2 - bug fix add missing files to pypi package
|
||||
- 0.2.1 - bug fix
|
||||
- 0.2 - security fix for XFF headers
|
||||
|
|
@ -49,6 +59,8 @@ Features
|
|||
- number of incorrect attempts before block
|
||||
- 95% code coverage
|
||||
- full documentation
|
||||
- Ability to store login attempts to the database
|
||||
- Management command to clean up login attempts database table
|
||||
- admin pages
|
||||
- list of blocked usernames and ip's
|
||||
- ability to unblock people
|
||||
|
|
@ -229,6 +241,29 @@ urlpatterns = patterns(
|
|||
)
|
||||
```
|
||||
|
||||
Management Commands:
|
||||
--------------------
|
||||
|
||||
``cleanup_django_defender``:
|
||||
|
||||
If you have a website with a lot of traffic, the AccessAttempts table will get
|
||||
full pretty quickly. If you don't need to keep the data for auditing purposes
|
||||
there is a management command to help you keep it clean.
|
||||
|
||||
It will look at your ``DEFENDER_ACCESS_ATTEMPT_EXPIRATION`` setting to determine
|
||||
which records will be deleted. Default if not specified, is 24 hours.
|
||||
|
||||
```bash
|
||||
$ python manage.py cleanup_django_defender
|
||||
```
|
||||
|
||||
You can set this up as a daily or weekly cron job to keep the table size down.
|
||||
|
||||
```bash
|
||||
# run at 12:24 AM every morning.
|
||||
24 0 * * * /usr/bin/python manage.py cleanup_django_defender >> /var/log/django_defender_cleanup.log
|
||||
```
|
||||
|
||||
|
||||
Admin Pages:
|
||||
------------
|
||||
|
|
@ -285,9 +320,17 @@ locked out.
|
|||
* ``DEFENDER_REDIS_URL``: String: the redis url for defender.
|
||||
[Default: ``redis://localhost:6379/0``]
|
||||
(Example with password: ``redis://:mypassword@localhost:6379/0``)
|
||||
* ``DEFENDER_STORE_ACCESS_ATTEMPTS``: Boolean: If you want to store the login
|
||||
attempt to the database, set to True. If False, it is not saved
|
||||
[Default: ``True``]
|
||||
* ``DEFENDER_USE_CELERY``: Boolean: If you want to use Celery to store the login
|
||||
attempt to the database, set to True. If False, it is saved inline.
|
||||
[Default: ``False``]
|
||||
* ``DEFENDER_ACCESS_ATTEMPT_EXPIRATION``: Int: Length of time in hours for how
|
||||
long to keep the access attempt records in the database before the management
|
||||
command cleans them up.
|
||||
[Default: 24]
|
||||
|
||||
|
||||
Running Tests
|
||||
=============
|
||||
|
|
|
|||
|
|
@ -13,17 +13,12 @@ class AccessAttemptAdmin(admin.ModelAdmin):
|
|||
)
|
||||
|
||||
list_filter = [
|
||||
'attempt_time',
|
||||
'ip_address',
|
||||
'username',
|
||||
'path_info',
|
||||
]
|
||||
|
||||
search_fields = [
|
||||
'ip_address',
|
||||
'username',
|
||||
'user_agent',
|
||||
'path_info',
|
||||
]
|
||||
|
||||
date_hierarchy = 'attempt_time'
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@ try:
|
|||
# how long to wait before the bad login attempt gets forgotten. in seconds.
|
||||
COOLOFF_TIME = int(get_setting('DEFENDER_COOLOFF_TIME', 300)) # seconds
|
||||
except ValueError: # pragma: no cover
|
||||
raise Exception('COOLOFF_TIME needs to be an integer') # pragma: no cover
|
||||
raise Exception(
|
||||
'DEFENDER_COOLOFF_TIME needs to be an integer') # pragma: no cover
|
||||
|
||||
LOCKOUT_TEMPLATE = get_setting('DEFENDER_LOCKOUT_TEMPLATE')
|
||||
|
||||
|
|
@ -45,5 +46,16 @@ USERNAME_FORM_FIELD = get_setting('DEFENDER_USERNAME_FORM_FIELD', 'username')
|
|||
|
||||
LOCKOUT_URL = get_setting('DEFENDER_LOCKOUT_URL')
|
||||
|
||||
|
||||
USE_CELERY = get_setting('DEFENDER_USE_CELERY', False)
|
||||
|
||||
STORE_ACCESS_ATTEMPTS = get_setting('DEFENDER_STORE_ACCESS_ATTEMPTS', True)
|
||||
|
||||
# Used by the management command to decide how long to keep access attempt
|
||||
# recods. Number is # of hours.
|
||||
try:
|
||||
ACCESS_ATTEMPT_EXPIRATION = int(get_setting(
|
||||
'DEFENDER_ACCESS_ATTEMPT_EXPIRATION', 24))
|
||||
except ValueError: # pragma: no cover
|
||||
raise Exception(
|
||||
'DEFENDER_ACCESS_ATTEMPT_EXPIRATION'
|
||||
' needs to be an integer') # pragma: no cover
|
||||
|
|
|
|||
|
|
@ -275,6 +275,11 @@ def check_request(request, login_unsuccessful):
|
|||
def add_login_attempt_to_db(request, login_valid):
|
||||
""" Create a record for the login attempt If using celery call celery
|
||||
task, if not, call the method normally """
|
||||
|
||||
if not config.STORE_ACCESS_ATTEMPTS:
|
||||
# If we don't want to store in the database, then don't proceed.
|
||||
return
|
||||
|
||||
user_agent = request.META.get('HTTP_USER_AGENT', '<unknown>')[:255]
|
||||
ip_address = get_ip(request)
|
||||
username = request.POST.get(config.USERNAME_FORM_FIELD, None)
|
||||
|
|
|
|||
6
setup.py
6
setup.py
|
|
@ -9,7 +9,7 @@ except ImportError:
|
|||
from distutils.core import setup
|
||||
|
||||
|
||||
version = '0.2.2'
|
||||
version = '0.3'
|
||||
|
||||
|
||||
def get_packages(package):
|
||||
|
|
@ -44,7 +44,7 @@ setup(name='django-defender',
|
|||
long_description="redis based Django app based on speed, that locks out"
|
||||
"users after too many failed login attempts.",
|
||||
classifiers=[
|
||||
'Development Status :: 4 - Beta',
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Framework :: Django',
|
||||
'Intended Audience :: Developers',
|
||||
'License :: OSI Approved :: Apache Software License',
|
||||
|
|
@ -69,6 +69,6 @@ setup(name='django-defender',
|
|||
packages=get_packages('defender'),
|
||||
package_data=get_package_data('defender'),
|
||||
install_requires=['Django>=1.6,<1.8', 'redis==2.10.3',
|
||||
'hiredis==0.1.4', 'mockredispy==2.9.0.10'],
|
||||
'hiredis==0.1.6', 'mockredispy==2.9.0.10'],
|
||||
tests_require=['mock', 'mockredispy', 'coverage', 'celery'],
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue