mirror of
https://github.com/jazzband/django-axes.git
synced 2026-03-16 22:30:23 +00:00
Improve documentation
This commit is contained in:
parent
fb2bd57c33
commit
0a90a7d075
14 changed files with 140 additions and 66 deletions
|
|
@ -13,13 +13,13 @@ class AxesBackend(ModelBackend):
|
|||
Use this class as the first item of ``AUTHENTICATION_BACKENDS`` to
|
||||
prevent locked out users from being logged in by the Django authentication flow.
|
||||
|
||||
**Note:** this backend does not log your user in and delegates login to the
|
||||
backends that are configured after it in the ``AUTHENTICATION_BACKENDS`` list.
|
||||
.. note:: This backend does not log your user in. It monitors login attempts.
|
||||
Authentication is handled by the following backends that are configured in ``AUTHENTICATION_BACKENDS``.
|
||||
"""
|
||||
|
||||
def authenticate(self, request: AxesHttpRequest, username: str = None, password: str = None, **kwargs: dict):
|
||||
"""
|
||||
Checks user lockout status and raise a PermissionDenied if user is not allowed to log in.
|
||||
Checks user lockout status and raises an exception if user is not allowed to log in.
|
||||
|
||||
This method interrupts the login flow and inserts error message directly to the
|
||||
``response_context`` attribute that is supplied as a keyword argument.
|
||||
|
|
@ -57,4 +57,6 @@ class AxesBackend(ModelBackend):
|
|||
class AxesModelBackend(AxesBackend):
|
||||
"""
|
||||
Backwards compatibility class for version 4 to version 5 migration.
|
||||
|
||||
See the ``AxesBackend`` class documentation and implementation.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -9,12 +9,14 @@ from axes.request import AxesHttpRequest
|
|||
|
||||
class AxesHandler: # pylint: disable=unused-argument
|
||||
"""
|
||||
Virtual handler API definition for subclassing handlers that can be used with the ``AxesProxyHandler``.
|
||||
Handler API definition for implementations that are used by the ``AxesProxyHandler``.
|
||||
|
||||
If you wish to implement your own handler class just override the methods you wish to specialize
|
||||
and define the class to be used with ``settings.AXES_HANDLER = 'path.to.YourClass'``.
|
||||
If you wish to specialize your own handler class, override the necessary methods
|
||||
and configure the class for use by setting ``settings.AXES_HANDLER = 'module.path.to.YourClass'``.
|
||||
|
||||
The default implementation that is actually used by Axes is the ``axes.handlers.database.AxesDatabaseHandler``.
|
||||
The default implementation that is actually used by Axes is ``axes.handlers.database.AxesDatabaseHandler``.
|
||||
|
||||
.. note:: This is a virtual class and **can not be used without specialization**.
|
||||
"""
|
||||
|
||||
def is_allowed(self, request: AxesHttpRequest, credentials: dict = None) -> bool:
|
||||
|
|
@ -23,7 +25,7 @@ class AxesHandler: # pylint: disable=unused-argument
|
|||
|
||||
This method is abstract and other backends can specialize it as needed, but the default implementation
|
||||
checks if the user has attempted to authenticate into the site too many times through the
|
||||
Django authentication backends and returns ``False``if user exceeds the configured Axes thresholds.
|
||||
Django authentication backends and returns ``False`` if user exceeds the configured Axes thresholds.
|
||||
|
||||
This checker can implement arbitrary checks such as IP whitelisting or blacklisting,
|
||||
request frequency checking, failed attempt monitoring or similar functions.
|
||||
|
|
|
|||
|
|
@ -16,16 +16,26 @@ from axes.request import AxesHttpRequest
|
|||
|
||||
class AxesMiddleware:
|
||||
"""
|
||||
Middleware that maps lockout signals into readable HTTP 403 Forbidden responses.
|
||||
Middleware that calculates necessary HTTP request attributes for attempt monitoring
|
||||
and maps lockout signals into readable HTTP 403 Forbidden responses.
|
||||
|
||||
Without this middleware the backend returns HTTP 403 errors with the
|
||||
``django.views.defaults.permission_denied`` view that renders the ``403.html``
|
||||
template from the root template directory if found.
|
||||
This middleware uses the ``axes.helpers.get_lockout_response`` handler
|
||||
for returning a context aware lockout message to the end user.
|
||||
By default Django server returns ``PermissionDenied`` exceptions as HTTP 403 errors
|
||||
with the ``django.views.defaults.permission_denied`` view that renders
|
||||
the ``403.html`` template from the root template directory if found.
|
||||
|
||||
To customize the error rendering, you can subclass this middleware
|
||||
This middleware recognizes the specialized attempt monitoring and lockout exceptions
|
||||
and uses the ``axes.helpers.get_lockout_response`` handler for returning
|
||||
customizable and context aware lockout message to the end user.
|
||||
|
||||
To customize the error handling behaviour further, you can subclass this middleware
|
||||
and change the ``process_exception`` handler to your own liking.
|
||||
|
||||
Please see the following configuration flags before customizing this handler:
|
||||
|
||||
- ``AXES_LOCKOUT_TEMPLATE``,
|
||||
- ``AXES_LOCKOUT_URL``,
|
||||
- ``AXES_COOLOFF_MESSAGE``, and
|
||||
- ``AXES_PERMALOCK_MESSAGE``.
|
||||
"""
|
||||
|
||||
def __init__(self, get_response: Callable):
|
||||
|
|
@ -37,9 +47,11 @@ class AxesMiddleware:
|
|||
|
||||
def update_request(self, request: HttpRequest):
|
||||
"""
|
||||
Update given Django ``HttpRequest`` with necessary attributes
|
||||
before passing it on the ``get_response`` for further
|
||||
Django middleware and view processing.
|
||||
Construct an ``AxesHttpRequest`` from the given ``HttpRequest``
|
||||
by updating the request with necessary attempt tracking attributes.
|
||||
|
||||
This method is called by the middleware class ``__call__`` method
|
||||
when iterating over the middleware stack.
|
||||
"""
|
||||
|
||||
request.axes_attempt_time = now()
|
||||
|
|
@ -50,9 +62,11 @@ class AxesMiddleware:
|
|||
|
||||
def process_exception(self, request: AxesHttpRequest, exception): # pylint: disable=inconsistent-return-statements
|
||||
"""
|
||||
Exception handler that processes exceptions raised by the Axes signal handler when request fails with login.
|
||||
Handle exceptions raised by the Axes signal handler class when requests fail checks.
|
||||
|
||||
Only ``axes.exceptions.AxesSignalPermissionDenied`` exception is handled by this middleware.
|
||||
Note that only ``AxesSignalPermissionDenied`` is handled by this middleware class.
|
||||
|
||||
:return: Configured ``HttpResponse`` for failed authentication attempts and lockouts.
|
||||
"""
|
||||
|
||||
if isinstance(exception, AxesSignalPermissionDenied):
|
||||
|
|
|
|||
|
|
@ -5,7 +5,30 @@ from django.http import HttpRequest
|
|||
|
||||
class AxesHttpRequest(HttpRequest):
|
||||
"""
|
||||
Type definition for the HTTP request Axes uses.
|
||||
Extended Django ``HttpRequest`` with custom Axes attributes.
|
||||
|
||||
This request is constructed by the ``AxesMiddleware`` class
|
||||
where the custom attributes are inserted into the request.
|
||||
|
||||
.. note:: The ``str`` type variables have a maximum length of 255
|
||||
characters and they are calculated in the middleware layer.
|
||||
If the HTTP request attributes can not be resolved
|
||||
they are assigned default value of ``<unknown>``.
|
||||
|
||||
:var axes_attempt_time: Timestamp of the request on the server side.
|
||||
:vartype axes_attempt_time: datetime
|
||||
|
||||
:var axes_ip_address: Request IP address as resolved by django-axes and django-ipware configurations.
|
||||
:vartype axes_ip_address: str
|
||||
|
||||
:var axes_user_agent: Request agent from ``request.META['HTTP_USER_AGENT']``.
|
||||
:vartype axes_user_agent: str
|
||||
|
||||
:var axes_path_info: Request path from ``request.META['PATH_INFO']``.
|
||||
:vartype axes_path_info: str
|
||||
|
||||
:var axes_http_accept: Request ``Accept`` header from ``request.META['HTTP_ACCEPT']``.
|
||||
:vartype axes_http_accept: str
|
||||
"""
|
||||
|
||||
axes_attempt_time: datetime
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
.. _requirements:
|
||||
|
||||
1. Requirements
|
||||
===============
|
||||
Requirements
|
||||
============
|
||||
|
||||
Axes requires a supported Django version and runs on Python and PyPy versions 3.5 and above.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
.. _installation:
|
||||
|
||||
2. Installation
|
||||
===============
|
||||
Installation
|
||||
============
|
||||
|
||||
Axes is easy to install from the PyPI package::
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ After installing the package, the project settings need to be configured.
|
|||
Axes is now functional with the default settings and is saving user attempts
|
||||
into your database and locking users out if they exceed the maximum attempts.
|
||||
|
||||
You should use the ``python manage.py check`` command to verify the correct configuration in both
|
||||
You should use the ``python manage.py check`` command to verify the correct configuration in
|
||||
development, staging, and production environments. It is probably best to use this step as part
|
||||
of your regular CI workflows to verify that your project is not misconfigured.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
.. _usage:
|
||||
|
||||
3. Usage
|
||||
========
|
||||
Usage
|
||||
=====
|
||||
|
||||
Once Axes is is installed and configured, you can login and logout
|
||||
of your application via the ``django.contrib.auth`` views.
|
||||
|
|
@ -31,4 +31,4 @@ In your code, you can use the ``axes.utils.reset`` function.
|
|||
Please note that if you give both ``username`` and ``ip`` arguments to ``reset``
|
||||
that attempts that have both the set IP and username are reset.
|
||||
|
||||
The effective behaviour of ``reset`` is to ``and`` the terms instead of ``or``ing them.
|
||||
The effective behaviour of ``reset`` is to ``and`` the terms instead of ``or`` ing them.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
.. _configuration:
|
||||
|
||||
4. Configuration
|
||||
================
|
||||
Configuration
|
||||
=============
|
||||
|
||||
Minimal Axes configuration is done with just ``settings.py`` updates.
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ The following ``settings.py`` options are available for customizing Axes behavio
|
|||
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
|
||||
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``
|
||||
|
|
@ -100,10 +100,10 @@ following settings to suit your set up to correctly resolve client IP addresses:
|
|||
Configuring handlers
|
||||
--------------------
|
||||
|
||||
Axes uses and provides handlers for processing signals and events
|
||||
Axes uses handlers for processing signals and events
|
||||
from Django authentication and login attempts.
|
||||
|
||||
The following handlers are offered by default and can be configured
|
||||
The following handlers are implemented by Axes and can be configured
|
||||
with the ``AXES_HANDLER`` setting in project configuration:
|
||||
|
||||
- ``axes.handlers.database.AxesDatabaseHandler``
|
||||
|
|
@ -126,6 +126,12 @@ with the ``AXES_HANDLER`` setting in project configuration:
|
|||
and is meant to be used on e.g. local development setups
|
||||
and testing deployments where login monitoring is not wanted.
|
||||
|
||||
To switch to cache based attempt tracking you can do the following::
|
||||
|
||||
AXES_HANDLER = 'axes.handlers.cache.AxesCacheHandler'
|
||||
|
||||
See the cache configuration section for suitable cache backends.
|
||||
|
||||
|
||||
Configuring caches
|
||||
------------------
|
||||
|
|
@ -140,8 +146,10 @@ resets made in the command line might not remove lock-outs that are in a sepate
|
|||
processes in-memory cache such as the web server serving your login or admin page.
|
||||
|
||||
To circumvent this problem, please use somethings else than
|
||||
``django.core.cache.backends.locmem.LocMemCache`` as your
|
||||
cache backend in Django cache ``BACKEND`` setting.
|
||||
``django.core.cache.backends.dummy.DummyCache``,
|
||||
``django.core.cache.backends.locmem.LocMemCache``, or
|
||||
``django.core.cache.backends.filebased.FileBasedCache``
|
||||
as your cache backend in Django cache ``BACKEND`` setting.
|
||||
|
||||
If changing the ``'default'`` cache is not an option, you can add a cache
|
||||
specifically for use with Axes. This is a two step process. First you need to
|
||||
|
|
|
|||
|
|
@ -1,9 +1,20 @@
|
|||
.. customization:
|
||||
|
||||
5. Customization
|
||||
================
|
||||
Customization
|
||||
=============
|
||||
|
||||
Axes can be customized and extended by using the correct signals.
|
||||
Axes has multiple options for customization including customizing the
|
||||
attempt tracking and lockout handling logic and lockout response formatting.
|
||||
|
||||
There are public APIs and the whole Axes tracking system is pluggable.
|
||||
You can swap the authentication backend, attempt tracker, failure handlers,
|
||||
database or cache backends and error formatters as you see fit.
|
||||
|
||||
Check the API reference section for further inspiration on
|
||||
implementing custom authentication backends, middleware, and handlers.
|
||||
|
||||
Axes uses the stock Django signals for login monitoring and
|
||||
can be customized and extended by using them correctly.
|
||||
|
||||
Axes listens to the following signals from ``django.contrib.auth.signals`` to log access attempts:
|
||||
|
||||
|
|
@ -15,6 +26,7 @@ You can also use Axes with your own auth module, but you'll need
|
|||
to ensure that it sends the correct signals in order for Axes to
|
||||
log the access attempts.
|
||||
|
||||
|
||||
Customizing authentication views
|
||||
--------------------------------
|
||||
|
||||
|
|
@ -140,4 +152,4 @@ into ``my_namespace-username``:
|
|||
NOTE: You still have to make these modifications yourself before calling
|
||||
authenticate. If you want to re-use the same function for consistency, that's
|
||||
fine, but Axes does not inject these changes into the authentication flow
|
||||
for you.
|
||||
for you.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
.. _integration:
|
||||
|
||||
6. Integration
|
||||
==============
|
||||
Integration
|
||||
===========
|
||||
|
||||
Axes is intended to be pluggable and usable with 3rd party authentication solutions.
|
||||
|
||||
|
|
@ -9,7 +9,7 @@ This document describes the integration with some commonly used 3rd party packag
|
|||
such as Django Allauth and Django REST Framework.
|
||||
|
||||
|
||||
Integrating with Django Allauth
|
||||
Integration with Django Allauth
|
||||
-------------------------------
|
||||
|
||||
Axes relies on having login information stored under ``AXES_USERNAME_FORM_FIELD`` key
|
||||
|
|
@ -64,7 +64,7 @@ You also need to decorate ``dispatch()`` and ``form_invalid()`` methods of the A
|
|||
]
|
||||
|
||||
|
||||
Integrating with Django REST Framework
|
||||
Integration with Django REST Framework
|
||||
--------------------------------------
|
||||
|
||||
Modern versions of Django REST Framework after 3.7.0 work normally with Axes.
|
||||
|
|
@ -108,7 +108,7 @@ require the request object to be passed for authentication.
|
|||
return (user, None)
|
||||
|
||||
|
||||
Integrating with Django Simple Captcha
|
||||
Integration with Django Simple Captcha
|
||||
--------------------------------------
|
||||
|
||||
Axes supports Captcha with the Django Simple Captcha package in the following manner.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
.. _architecture:
|
||||
|
||||
7. Architecture
|
||||
================
|
||||
Architecture
|
||||
============
|
||||
|
||||
Axes is based on the existing Django authentication backend
|
||||
architecture and framework for recognizing users and aims to be
|
||||
|
|
|
|||
|
|
@ -1,17 +1,22 @@
|
|||
.. _reference:
|
||||
|
||||
8. API reference
|
||||
================
|
||||
API reference
|
||||
=============
|
||||
|
||||
Axes offers extendable APIs that you can customize to your liking.
|
||||
You can specialize the following base classes or alternatively implement
|
||||
your own classes based on top of the following base implementations.
|
||||
Axes offers extensible APIs that you can customize to your liking.
|
||||
You can specialize the following base classes or alternatively use
|
||||
third party modules as long as they implement the following APIs.
|
||||
|
||||
.. automodule:: axes.handlers.base
|
||||
:members:
|
||||
|
||||
.. automodule:: axes.backends
|
||||
:members:
|
||||
:show-inheritance:
|
||||
|
||||
.. automodule:: axes.middleware
|
||||
:members:
|
||||
|
||||
.. automodule:: axes.handlers.base
|
||||
.. automodule:: axes.request
|
||||
:members:
|
||||
:show-inheritance:
|
||||
|
|
|
|||
|
|
@ -1,24 +1,27 @@
|
|||
.. _development:
|
||||
|
||||
9. Development
|
||||
==============
|
||||
Development
|
||||
===========
|
||||
|
||||
You can contribute to this project forking it from GitHub and sending pull requests.
|
||||
|
||||
First `fork <https://help.github.com/en/articles/fork-a-repo>`_ the
|
||||
`repository <https://github.com/jazzband/django-axes>`_ and then clone it::
|
||||
|
||||
Setting up a development environment
|
||||
------------------------------------
|
||||
$ git clone git@github.com:<you>/django-axes.git
|
||||
|
||||
Fork and clone the repository, initialize a virtual environment and install the requirements::
|
||||
Initialize a virtual environment for development purposes::
|
||||
|
||||
$ git clone git@github.com:<fork>/django-axes.git
|
||||
$ cd django-axes
|
||||
$ mkdir ~/.virtualenvs
|
||||
$ mkdir -p ~/.virtualenvs
|
||||
$ python3 -m venv ~/.virtualenvs/django-axes
|
||||
$ source ~/.virtualenvs/bin/activate
|
||||
$ source ~/.virtualenvs/django-axes/bin/activate
|
||||
|
||||
Then install the necessary requirements::
|
||||
|
||||
$ cd django-axes
|
||||
$ pip install -r requirements.txt
|
||||
|
||||
Unit tests that are in the `axes/tests` folder can be run easily with the ``axes.tests.settings`` configuration::
|
||||
Unit tests are located in the ``axes/tests`` folder and can be easily run with the pytest tool::
|
||||
|
||||
$ pytest
|
||||
|
||||
|
|
@ -30,10 +33,14 @@ Mypy runs static typing checks to verify the source code type annotations and co
|
|||
|
||||
$ mypy .
|
||||
|
||||
Before committing, you can run all the tests against all supported Django versions with tox::
|
||||
Before committing, you can run all the above tests against all supported Python and Django versions with tox::
|
||||
|
||||
$ tox
|
||||
|
||||
Tox runs the same tests that are run by Travis, and your code should be good to go if it passes.
|
||||
Tox runs the same test set that is run by Travis, and your code should be good to go if it passes.
|
||||
|
||||
After you have made your changes, open a pull request on GitHub for getting your code upstreamed.
|
||||
If you wish to limit the testing to specific environment(s), you can parametrize the tox run::
|
||||
|
||||
$ tox -e py37-django21
|
||||
|
||||
After you have pushed your changes, open a pull request on GitHub for getting your code upstreamed.
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ Contents
|
|||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:numbered:
|
||||
|
||||
1_requirements
|
||||
2_installation
|
||||
|
|
|
|||
Loading…
Reference in a new issue