Django-altcha-middleware (dam) is meant to be a proof-of-work deterrent for bots. This Django app uses Altcha to create a challenge for protected pages that is solved by using cryptographic functions to find a hidden number. Once a user successfully solves a challenge (done automatically by the browser, no user input required), they will not be challenged again for a period defined by ALTCHA_AUTH_EXPIRE_MINUTES. This app may be used to protect an entire site by using the provided middleware, or only certain views by using the provided decorator.
- Python 3.9-3.13
- Django 4.2-5.2
To install this app into your existing Django project:
- Install the django-altcha-middleware package into your Python installation
(if using a virtual environment, for instance, activate it first):
$ pip install git+https://github.com/unt-libraries/django-altcha-middleware
- Within your project's settings file, add
dam
to your Django project's INSTALLED_APPS list and defineALTCHA_HMAC_KEY
andALTCHA_MAX_NUMBER
, as well as the other settings if you'd like to override their default values (shown below):INSTALLED_APPS = [ ..., 'dam', ] ALTCHA_HMAC_KEY = 'something' # REQUIRED: Secret string used for challenges. ALTCHA_MAX_NUMBER = 50000 # REQUIRED: Altcha challenge difficulty. ALTCHA_AUTH_EXPIRE_MINUTES = 480 # Minutes the user is authorized for after solving a challenge. ALTCHA_CHALLENGE_EXPIRE_MINUTES = 2 # Minutes before a given challenge expires. ALTCHA_SALT_PARAMS = {} # Additional query parameters to append to the challenge salt. ALTCHA_SESSION_KEY = 'altcha_verified' # Session key name that tracks successful challenges. ALTCHA_SITE_ICON_URL = '' # Where to find the site icon for use on the challenge page. ALTCHA_JS_URL = (f'{STATIC_URL}altcha/' # Where to find the altcha widget JS. 'altcha.min.js') ALTCHA_CSS_URL = f'{STATIC_URL}dam/dam.css' # Where to find the altcha widget CSS. ALTCHA_MESSAGE = ('Gauging your humanity...' # Message to present to users on the challenge page. 'This may take some seconds.') ALTCHA_HELP_MESSAGE = '' # Message shown on challenge page and in errors indicating how to seek help on challenge failure/error. ALTCHA_FAIL_MESSAGE = ('Challenge failed or no' # Message to show users when their challenge response is unsuccessful. ' longer valid.') ALTCHA_EXCLUDE_PATHS = set() # Set of paths to exclude from challenges. ALTCHA_EXCLUDE_IPS = [] # List of strings representing CIDRs or IPs to never challenge. ALTCHA_EXCLUDE_HEADERS = {} # Dict of HTTP header keys (case insensitive) with values to exempt from challenge. # Values should be given as raw strings as the middleware converts them to case-insensitive regex patterns. # Example: {'User-Agent': r'Googlebot|Siteimprove\.com'}
- Add the challenge URL to your project's urls.py module:
urlpatterns = [ ..., path('', include('dam.urls')), ]
- Decide whether you'd like to protect individual views or your whole site.
- If you'd like to protect your whole site with
dam
, then add it to your MIDDLEWARE list in your settings file:MIDDLEWARE = [ ..., 'dam.middleware.AltchaMiddleware', ]
- Or, if you'd like to only protect certain views, then use the
@dam
decorator on them:from dam.decorators import dam ... @dam def my_precious_view(request): """I don't want bots crawling this page.""" ... return HttpResponse("Can't touch this!")
- If you'd like to protect your whole site with
Follow the steps below to set up a development environment for if you'd like to be able to test out the project without setting up your own Django project, run the unit tests, or make changes.
- Clone this repo and then navigate inside of it:
$ git clone [email protected]:unt-libraries/django-altcha-middleware.git && cd django-altcha-middleware
- Set up a Python virtual environment and then activate it:
$ python3 -m venv env && source env/bin/activate
- Install the main and test requirements:
$ pip install -rrequirements.txt -rrequirements-test.txt
- Start the Django test server:
$ python3 manage.py runserver
- While that is running, open your browser and you can experience the challenge page by visiting
http://localhost:8000/protected. The test project is set up to protect the
/protected
page (redirecting to the/
challenge page until the challenge is solved, then redirecting again to/protected
after completing the challenge) while leaving the/open
page available with no challenge. - When you are done viewing the pages, you can stop the test server with CTRL-C.
- To run the unit tests against all available versions of Python from 3.9 - 3.13, as well as the
Ruff lint/style checks and coverage report:
$ tox
See LICENSE.txt