|
|
@@ -1,490 +0,0 @@
|
|
|
-Metadata-Version: 1.1
|
|
|
-Name: django-axes
|
|
|
-Version: 1.6.0
|
|
|
-Summary: Keep track of failed login attempts in Django-powered sites.
|
|
|
-Home-page: https://github.com/django-pci/django-axes
|
|
|
-Author: Alex Clark
|
|
|
-Author-email: aclark@aclark.net
|
|
|
-License: MIT
|
|
|
-Description: Django Axes
|
|
|
- ===========
|
|
|
-
|
|
|
- .. image:: https://secure.travis-ci.org/django-pci/django-axes.png?branch=master
|
|
|
- :alt: Build Status
|
|
|
- :target: http://travis-ci.org/django-pci/django-axes
|
|
|
-
|
|
|
- ``django-axes`` is a very simple way for you to keep track of failed login
|
|
|
- attempts, both for the Django admin and for the rest of your site. The name is
|
|
|
- sort of a geeky pun, since ``axes`` can be read interpreted as:
|
|
|
-
|
|
|
- * "access", as in monitoring access attempts
|
|
|
- * "axes", as in tools you can use hack (generally on wood). In this case,
|
|
|
- however, the "hacking" part of it can be taken a bit further: ``django-axes``
|
|
|
- is intended to help you *stop* people from hacking (popular media
|
|
|
- definition) your website. Hilarious, right? That's what I thought too!
|
|
|
-
|
|
|
-
|
|
|
- Requirements
|
|
|
- ============
|
|
|
-
|
|
|
- ``django-axes`` requires Django 1.5 or later. The application is intended to
|
|
|
- work around the Django admin and the regular ``django.contrib.auth``
|
|
|
- login-powered pages.
|
|
|
-
|
|
|
-
|
|
|
- Installation
|
|
|
- ============
|
|
|
-
|
|
|
- You can install the latest stable package running this command::
|
|
|
-
|
|
|
- $ pip install django-axes
|
|
|
-
|
|
|
- Also you can install the development version running this command::
|
|
|
-
|
|
|
- $ pip install -e git+http://github.com/django-pci/django-axes.git#egg=django_axes-dev
|
|
|
-
|
|
|
- Development
|
|
|
- ===========
|
|
|
-
|
|
|
- You can contribute to this project forking it from github and sending pull requests.
|
|
|
-
|
|
|
- Running tests
|
|
|
- -------------
|
|
|
-
|
|
|
- Tests can be run, after you clone the repository and having django installed, like::
|
|
|
-
|
|
|
- $ PYTHONPATH=$PYTHONPATH:$PWD django-admin.py test axes --settings=axes.test_settings
|
|
|
-
|
|
|
-
|
|
|
- Configuration
|
|
|
- =============
|
|
|
-
|
|
|
- First of all, you must add this project to your list of ``INSTALLED_APPS`` in
|
|
|
- ``settings.py``::
|
|
|
-
|
|
|
- INSTALLED_APPS = (
|
|
|
- 'django.contrib.admin',
|
|
|
- 'django.contrib.auth',
|
|
|
- 'django.contrib.contenttypes',
|
|
|
- 'django.contrib.sessions',
|
|
|
- 'django.contrib.sites',
|
|
|
- ...
|
|
|
- 'axes',
|
|
|
- ...
|
|
|
- )
|
|
|
-
|
|
|
- Next, install the ``FailedLoginMiddleware`` middleware::
|
|
|
-
|
|
|
- MIDDLEWARE_CLASSES = (
|
|
|
- 'django.middleware.common.CommonMiddleware',
|
|
|
- 'django.contrib.sessions.middleware.SessionMiddleware',
|
|
|
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
|
|
|
- 'axes.middleware.FailedLoginMiddleware'
|
|
|
- )
|
|
|
-
|
|
|
- Run ``python manage.py syncdb``. This creates the appropriate tables in your database
|
|
|
- that are necessary for operation.
|
|
|
-
|
|
|
- Customizing Axes
|
|
|
- ----------------
|
|
|
-
|
|
|
- You have a couple options available to you to customize ``django-axes`` a bit.
|
|
|
- These should be defined in your ``settings.py`` file.
|
|
|
-
|
|
|
- * ``AXES_LOGIN_FAILURE_LIMIT``: The number of login attempts allowed before a
|
|
|
- record is created for the failed logins. Default: ``3``
|
|
|
- * ``AXES_LOCK_OUT_AT_FAILURE``: After the number of allowed login attempts
|
|
|
- are exceeded, should we lock out this IP (and optional user agent)?
|
|
|
- Default: ``True``
|
|
|
- * ``AXES_USE_USER_AGENT``: 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``
|
|
|
- * ``AXES_COOLOFF_TIME``: If set, defines a period of inactivity after which
|
|
|
- old failed login attempts will be forgotten. Can be set to a python
|
|
|
- timedelta object or an integer. If an integer, will be interpreted as a
|
|
|
- number of hours. Default: ``None``
|
|
|
- * ``AXES_LOGGER``: If set, specifies a logging mechanism for axes to use.
|
|
|
- Default: ``'axes.watch_login'``
|
|
|
- * ``AXES_LOCKOUT_TEMPLATE``: 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``
|
|
|
- * ``AXES_LOCKOUT_URL``: If set, specifies a URL to redirect to on lockout. If
|
|
|
- both AXES_LOCKOUT_TEMPLATE and AXES_LOCKOUT_URL are set, the template will
|
|
|
- be used. Default: ``None``
|
|
|
- * ``AXES_VERBOSE``: If ``True``, you'll see slightly more logging for Axes.
|
|
|
- Default: ``True``
|
|
|
- * ``AXES_USERNAME_FORM_FIELD``: the name of the form field that contains your
|
|
|
- users usernames. Default: ``username``
|
|
|
-
|
|
|
- * ``AXES_LOCK_OUT_BY_COMBINATION_USER_AND_IP``: If ``True`` prevents to login
|
|
|
- from IP under particular user if attempts limit exceed, otherwise lock out
|
|
|
- based on IP.
|
|
|
- Default: ``False``
|
|
|
-
|
|
|
-
|
|
|
- Usage
|
|
|
- =====
|
|
|
-
|
|
|
- Using ``django-axes`` is extremely simple. Once you install the application
|
|
|
- and the middleware, all you need to do is periodically check the Access
|
|
|
- Attempts section of the admin.
|
|
|
-
|
|
|
- By default, django-axes will lock out repeated attempts from the same IP
|
|
|
- address. You can allow this IP to attempt again by deleting the relevant
|
|
|
- ``AccessAttempt`` records in the admin.
|
|
|
-
|
|
|
- You can also use the ``axes_reset`` management command using Django's
|
|
|
- ``manage.py``.
|
|
|
-
|
|
|
- * ``manage.py axes_reset`` will reset all lockouts and access records.
|
|
|
- * ``manage.py axes_reset ip`` will clear lockout/records for ip
|
|
|
-
|
|
|
- In your code, you can use ``from axes.utils import reset``.
|
|
|
-
|
|
|
- * ``reset()`` will reset all lockouts and access records.
|
|
|
- * ``reset(ip=ip)`` will clear lockout/records for ip
|
|
|
- * ``reset(username=username)`` will clear lockout/records for username
|
|
|
-
|
|
|
- Issues
|
|
|
- ======
|
|
|
-
|
|
|
- Not being locked out after failed attempts
|
|
|
- ------------------------------------------
|
|
|
-
|
|
|
- You may find that Axes is not capturing your failed login attempts. It may be that you need to manually add watch_login to your login url.
|
|
|
- For example, in your urls.py::
|
|
|
-
|
|
|
- ...
|
|
|
- from django.contrib.auth.views import login, logout, password_change
|
|
|
- from axes.decorators import watch_login
|
|
|
- ...
|
|
|
- urlpatterns = patterns('',
|
|
|
- (r'^login/$', watch_login(login), {'template_name': 'auth/login.html'}),
|
|
|
- ...
|
|
|
-
|
|
|
-
|
|
|
- Locked out without reason
|
|
|
- -------------------------
|
|
|
-
|
|
|
- It may happen that you have suddenly become locked out without a single failed
|
|
|
- attempt. One possible reason is that you are using some custom login form and the
|
|
|
- username field is named something different than "username", e.g. "email". This
|
|
|
- leads to all users attempts being lumped together. To fix this add the following
|
|
|
- to your settings:
|
|
|
-
|
|
|
- AXES_USERNAME_FORM_FIELD = "email"
|
|
|
-
|
|
|
-
|
|
|
- Using a captcha
|
|
|
- ===============
|
|
|
-
|
|
|
- Using https://github.com/mbi/django-simple-captcha you do the following:
|
|
|
-
|
|
|
- 1. Change axes lockout url in ``settings.py``::
|
|
|
-
|
|
|
- AXES_LOCKOUT_URL = '/locked'
|
|
|
-
|
|
|
- 2. Add the url in ``urls.py``::
|
|
|
-
|
|
|
- url(r'^locked/$', locked_out, name='locked_out'),
|
|
|
-
|
|
|
- 3. Create a captcha form::
|
|
|
-
|
|
|
- class AxesCaptchaForm(forms.Form):
|
|
|
- captcha = CaptchaField()
|
|
|
-
|
|
|
- 4. Create a captcha view for the above url that resets on captcha success and redirects::
|
|
|
-
|
|
|
- def locked_out(request):
|
|
|
- if request.POST:
|
|
|
- form = AxesCaptchaForm(request.POST)
|
|
|
- if form.is_valid():
|
|
|
- ip = get_ip_address_from_request(request)
|
|
|
- reset(ip=ip)
|
|
|
- return HttpResponseRedirect(reverse_lazy('signin'))
|
|
|
- else:
|
|
|
- form = AxesCaptchaForm()
|
|
|
-
|
|
|
- return render_to_response('locked_out.html', dict(form=form), context_instance=RequestContext(request))
|
|
|
-
|
|
|
- 5. Add a captcha template::
|
|
|
-
|
|
|
- <form action="" method="post">
|
|
|
- {% csrf_token %}
|
|
|
-
|
|
|
- {{ form.captcha.errors }}
|
|
|
- {{ form.captcha }}
|
|
|
-
|
|
|
- <div class="form-actions">
|
|
|
- <input type="submit" value="Submit" />
|
|
|
- </div>
|
|
|
- </form>
|
|
|
-
|
|
|
- Done.
|
|
|
-
|
|
|
- Changes
|
|
|
- =======
|
|
|
-
|
|
|
- 1.6.0 (2016-01-07)
|
|
|
- ------------------
|
|
|
-
|
|
|
- - Stopped using render_to_response so that other template engines work
|
|
|
- [tarkatronic]
|
|
|
-
|
|
|
- - Improved performance & DoS prevention on query2str
|
|
|
- [tarkatronic]
|
|
|
-
|
|
|
- - Immediately return from is_already_locked if the user is not lockable
|
|
|
- [jdunck]
|
|
|
-
|
|
|
- - Iterate over ip addresses only once
|
|
|
- [annp89]
|
|
|
-
|
|
|
- - added initial migration files to support django 1.7 &up
|
|
|
- [ibaguio]
|
|
|
-
|
|
|
- - Add db indexes to CommonAccess model
|
|
|
- [Schweigi]
|
|
|
-
|
|
|
- 1.5.0 (2015-09-11)
|
|
|
- ------------------
|
|
|
-
|
|
|
- - Fix #_get_user_attempts to include username when filtering AccessAttempts if AXES_LOCK_OUT_BY_COMBINATION_USER_AND_IP is True
|
|
|
- [afioca]
|
|
|
-
|
|
|
- 1.4.0 (2015-08-09)
|
|
|
- ------------------
|
|
|
-
|
|
|
- - Send the user_locked_out signal. Fixes #94.
|
|
|
- [toabi]
|
|
|
-
|
|
|
- 1.3.9 (2015-02-11)
|
|
|
- ------------------
|
|
|
-
|
|
|
- - Python 3 fix (#104)
|
|
|
-
|
|
|
- 1.3.8 (2014-10-07)
|
|
|
- ------------------
|
|
|
-
|
|
|
- - Rename GitHub organization from django-security to django-pci to emphasize focus on providing assistance with building PCI compliant websites with Django.
|
|
|
- [aclark4life]
|
|
|
-
|
|
|
- 1.3.7 (2014-10-05)
|
|
|
- ------------------
|
|
|
-
|
|
|
- - Explain common issues where Axes fails silently
|
|
|
- [cericoda]
|
|
|
-
|
|
|
- - Allow for user-defined username field for lookup in POST data
|
|
|
- [SteveByerly]
|
|
|
-
|
|
|
- - Log out only if user was logged in
|
|
|
- [zoten]
|
|
|
-
|
|
|
- - Support for floats in cooloff time (i.e: 0.1 == 6 minutes)
|
|
|
- [marianov]
|
|
|
-
|
|
|
- - Limit amount of POST data logged (#73). Limiting the length of value is not enough, as there could be arbitrary number of them, or very long key names.
|
|
|
- [peterkuma]
|
|
|
-
|
|
|
- - Improve get_ip to try for real ip address
|
|
|
- [7wonders]
|
|
|
-
|
|
|
- - Change IPAddressField to GenericIPAddressField. When using a PostgreSQL database and the client does not pass an IP address you get an inet error. This is a known problem with PostgreSQL and the IPAddressField. https://code.djangoproject.com/ticket/5622. It can be fixed by using a GenericIPAddressField instead.
|
|
|
- [polvoblanco]
|
|
|
-
|
|
|
- - Get first X-Forwarded-For IP
|
|
|
- [tutumcloud]
|
|
|
-
|
|
|
- - White listing IP addresses behind reverse proxy. Allowing some IP addresses to have direct access to the app even if they are behind a reverse proxy. Those IP addresses must still be on a white list.
|
|
|
- [ericbulloch]
|
|
|
-
|
|
|
- - Reduce logging of reverse proxy IP lookup and use configured logger. Fixes #76. Instead of logging the notice that django.axes looks for a HTTP header set by a reverse proxy on each attempt, just log it one-time on first module import. Also use the configured logger (by default axes.watch_login) for the message to be more consistent in logging.
|
|
|
- [eht16]
|
|
|
-
|
|
|
- - Limit the length of the values logged into the database. Refs #73
|
|
|
- [camilonova]
|
|
|
-
|
|
|
- - Refactored tests to be more stable and faster
|
|
|
- [camilonova]
|
|
|
-
|
|
|
- - Clean client references
|
|
|
- [camilonova]
|
|
|
-
|
|
|
- - Fixed admin login url
|
|
|
- [camilonova]
|
|
|
-
|
|
|
- - Added django 1.7 for testing
|
|
|
- [camilonova]
|
|
|
-
|
|
|
- - Travis file cleanup
|
|
|
- [camilonova]
|
|
|
-
|
|
|
- - Remove hardcoded url path
|
|
|
- [camilonova]
|
|
|
-
|
|
|
- - Fixing tests for django 1.7
|
|
|
- [Andrew-Crosio]
|
|
|
-
|
|
|
- - Fix for django 1.7 exception not existing
|
|
|
- [Andrew-Crosio]
|
|
|
-
|
|
|
- - Removed python 2.6 from testing
|
|
|
- [camilonova]
|
|
|
-
|
|
|
- - Use django built-in six version
|
|
|
- [camilonova]
|
|
|
-
|
|
|
- - Added six as requirement
|
|
|
- [camilonova]
|
|
|
-
|
|
|
- - Added python 2.6 for travis testing
|
|
|
- [camilonova]
|
|
|
-
|
|
|
- - Replaced u string literal prefixes with six.u() calls
|
|
|
- [amrhassan]
|
|
|
-
|
|
|
- - Fixes object type issue, response is not an string
|
|
|
- [camilonova]
|
|
|
-
|
|
|
- - Python 3 compatibility fix for db_reset
|
|
|
- [nicois]
|
|
|
-
|
|
|
- - Added example project and helper scripts
|
|
|
- [barseghyanartur]
|
|
|
-
|
|
|
- - Admin command to list login attemps
|
|
|
- [marianov]
|
|
|
-
|
|
|
- - Replaced six imports with django.utils.six ones
|
|
|
- [amrhassan]
|
|
|
-
|
|
|
- - Replaced u string literal prefixes with six.u() calls to make it compatible with Python 3.2
|
|
|
- [amrhassan]
|
|
|
-
|
|
|
- - Replaced `assertIn`s and `assertNotIn`s with `assertContains` and `assertNotContains`
|
|
|
- [fcurella]
|
|
|
-
|
|
|
- - Added py3k to travis
|
|
|
- [fcurella]
|
|
|
-
|
|
|
- - Update test cases to be python3 compatible
|
|
|
- [nicois]
|
|
|
-
|
|
|
- - Python 3 compatibility fix for db_reset
|
|
|
- [nicois]
|
|
|
-
|
|
|
- - Removed trash from example urls
|
|
|
- [barseghyanartur]
|
|
|
-
|
|
|
- - Added django installer
|
|
|
- [barseghyanartur]
|
|
|
-
|
|
|
- - Added example project and helper scripts
|
|
|
- [barseghyanartur]
|
|
|
-
|
|
|
-
|
|
|
- 1.3.6 (2013-11-23)
|
|
|
- ------------------
|
|
|
-
|
|
|
- - Added AttributeError in case get_profile doesn't exist [camilonova]
|
|
|
- - Improved axes_reset command [camilonova]
|
|
|
-
|
|
|
-
|
|
|
- 1.3.5 (2013-11-01)
|
|
|
- ------------------
|
|
|
-
|
|
|
- - Fix an issue with __version__ loading the wrong version [graingert]
|
|
|
-
|
|
|
-
|
|
|
- 1.3.4 (2013-11-01)
|
|
|
- ------------------
|
|
|
-
|
|
|
- - Update README.rst for PyPI [marty] [camilonova] [graingert]
|
|
|
- - Add cooloff period [visualspace]
|
|
|
-
|
|
|
-
|
|
|
- 1.3.3 (2013-07-05)
|
|
|
- ------------------
|
|
|
-
|
|
|
- - Added 'username' field to the Admin table [bkvirendra]
|
|
|
- - Removed fallback logging creation since logging cames by default on django 1.4 or later, if you don't have it is because you explicitly wanted. Fixes #45 [camilonova]
|
|
|
-
|
|
|
-
|
|
|
- 1.3.2 (2013-03-28)
|
|
|
- ------------------
|
|
|
-
|
|
|
- - Fix an issue when a user logout [camilonova]
|
|
|
- - Match pypi version [camilonova]
|
|
|
- - Better User model import method [camilonova]
|
|
|
- - Use only one place to get the version number [camilonova]
|
|
|
- - Fixed an issue when a user on django 1.4 logout [camilonova]
|
|
|
- - Handle exception if there is not user profile model set [camilonova]
|
|
|
- - Made some cleanup and remove a pokemon exception handling [camilonova]
|
|
|
- - Improved tests so it really looks for the rabbit in the hole [camilonova]
|
|
|
- - Match pypi version [camilonova]
|
|
|
-
|
|
|
-
|
|
|
- 1.3.1 (2013-03-19)
|
|
|
- ------------------
|
|
|
-
|
|
|
- - Add support for Django 1.5 [camilonova]
|
|
|
-
|
|
|
-
|
|
|
- 1.3.0 (2013-02-27)
|
|
|
- ------------------
|
|
|
-
|
|
|
- - Bug fix: get_version() format string [csghormley]
|
|
|
-
|
|
|
-
|
|
|
- 1.2.9 (2013-02-20)
|
|
|
- ------------------
|
|
|
-
|
|
|
- - Add to and improve test cases [camilonova]
|
|
|
-
|
|
|
-
|
|
|
- 1.2.8 (2013-01-23)
|
|
|
- ------------------
|
|
|
-
|
|
|
- - Increased http accept header length [jslatts]
|
|
|
-
|
|
|
-
|
|
|
- 1.2.7 (2013-01-17)
|
|
|
- ------------------
|
|
|
-
|
|
|
- - Reverse proxy support [rmagee]
|
|
|
- - Clean up README [martey]
|
|
|
-
|
|
|
-
|
|
|
- 1.2.6 (2012-12-04)
|
|
|
- ------------------
|
|
|
-
|
|
|
- - Remove unused import [aclark4life]
|
|
|
-
|
|
|
-
|
|
|
- 1.2.5 (2012-11-28)
|
|
|
- ------------------
|
|
|
-
|
|
|
- - Fix setup.py [aclark4life]
|
|
|
- - Added ability to flag user accounts as unlockable. [kencochrane]
|
|
|
- - Added ipaddress as a param to the user_locked_out signal. [kencochrane]
|
|
|
- - Added a signal receiver for user_logged_out. [kencochrane]
|
|
|
- - Added a signal for when a user gets locked out. [kencochrane]
|
|
|
- - Added AccessLog model to log all access attempts. [kencochrane]
|
|
|
-
|
|
|
-Keywords: authentication,django,pci,security
|
|
|
-Platform: UNKNOWN
|
|
|
-Classifier: Development Status :: 5 - Production/Stable
|
|
|
-Classifier: Environment :: Web Environment
|
|
|
-Classifier: Framework :: Django
|
|
|
-Classifier: Intended Audience :: Developers
|
|
|
-Classifier: Intended Audience :: System Administrators
|
|
|
-Classifier: License :: OSI Approved :: MIT License
|
|
|
-Classifier: Operating System :: OS Independent
|
|
|
-Classifier: Programming Language :: Python
|
|
|
-Classifier: Programming Language :: Python :: 2.7
|
|
|
-Classifier: Programming Language :: Python :: 3
|
|
|
-Classifier: Topic :: Internet :: Log Analysis
|
|
|
-Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware
|
|
|
-Classifier: Topic :: Security
|
|
|
-Classifier: Topic :: System :: Logging
|