Adding CAPTCHA and Multiple Login Attempt Limits to Django-Admin
Django's built-in Admin is very useful, but it still feels a bit lacking for production = = Take a look at the Admin introduction: Django follows Python's batteries-included philosophy. It comes with a series of extra, optional tools for solving common problems or needs in web development. These tools and plugins, such as django.contrib.redirects, must be registered in INSTALLED_APPS in settings, and some also require running the manage.py migrate command
目录5 个章节
Django's built-in Admin is very useful, but it still feels a bit lacking for production = =
Take a look at the Admin introduction:
Django follows Python's batteries-included philosophy. It comes with a series of extra, optional tools for solving common problems or needs in web development. These tools and plugins, such as django.contrib.redirects, must be registered in INSTALLED_APPS in settings, and some also require running the manage.py migrate command to create some tables in the database.
The Admin site is the most important thing that sets Django apart from other web frameworks, and it's extremely popular—practically a must-have for going on a trip xxxx. Whether you're writing a small demo or building a large project, you'll find it useful. admin (hereinafter the Admin backend will be referred to as admin) quickly constructs a web site for managing actual data by reading your model data. It's commonly used for development testing, simple management, and similar scenarios, suitable for internal departmental use for work convenience, but it is not recommended for use in production.
Why is it not recommended for production? Because Admin lacks security features like CAPTCHA and login limits! If someone casually brute-forces their way into the backend, how can we guarantee our system's security?
But don't worry—I've already implemented CAPTCHA and login limits by hacking it a bit, so now we can happily use the admin system.
First, take a look at the result

The result looks pretty nice. The number of login attempts can be set yourself; I won't demo it here, since entering the wrong password that many times is too much of a hassle.
CAPTCHA
For the CAPTCHA I used the django-simple-captcha library, together with multi_captcha_admin to generate the CAPTCHA form—very convenient.
First, pip-install these two libraries; everyone knows how, so I won't go into details.
Configure settings.py:
INSTALLED_APPS = [
'multi_captcha_admin',
]
# 验证码配置
MULTI_CAPTCHA_ADMIN = {
'engine': 'simple-captcha',
}
Configure urls.py:
# 添加这一项
path('captcha/', include('captcha.urls')),
That's all it takes. If you're using Django's official Admin, the login CAPTCHA will show up directly. However, I'm using a third-party Admin, so I need to add the form manually.
The method is simple: find login.html and add this item inside the login form.
{{ form.captcha }}
The default generated CAPTCHA and input box use native styles, which look pretty ugly~ We can improve them a bit. I used js to replace the generated image and CAPTCHA input box with elementUI styles. Friends who need this can use it as a reference.
var row = document.querySelector('#captcha_group');
var captcha_img = document.querySelector('img.captcha');
var col_8 = document.createElement('el-col');
col_8.setAttribute(':span', '8');
col_8.appendChild(captcha_img);
var captcha_input = document.querySelector('#id_captcha_1');
var el_input = document.createElement('el-input');
var col_16 = document.createElement('el-col');
col_16.setAttribute(':span', '16');
el_input.setAttribute('name', captcha_input.getAttribute('name'));
el_input.setAttribute('v-model', 'captcha');
el_input.setAttribute('required', 'required');
el_input.setAttribute('placeholder', '请输入验证码');
col_16.appendChild(el_input);
captcha_input.parentNode.removeChild(captcha_input);
row.appendChild(col_8);
row.appendChild(col_16);
Login Rate Limiting
This isn't complicated either, but it still took me quite a while at first—I couldn't find much useful material. Later I went and read Django Admin's source code, and the solution came to me right away haha~
From the admin code, I found that login is handled by the admin.site.login(request, extra_context) method, so the problem becomes very simple: just add a decorator to it. However, we can't modify the framework's code, so we write a new view ourselves, as follows:
# 覆盖默认的admin登录方法实现登录限流
@ratelimit(key='ip', rate='5/m', block=True)
def extend_admin_login(request, extra_context=None):
return admin.site.login(request, extra_context)
Then configure it in urls.py, and remember to put it before admin:
urlpatterns = [
path('admin/login/', views.extend_admin_login),
path('admin/', admin.site.urls),
]
This way you can implement rate limiting. Here I'll introduce the ratelimit decorator, which is provided by the django-ratelimit package. To use this package, you need to configure redis cache. Here's the configuration code:
# 配置redis缓存
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache', # 缓存后端 Redis
# 连接Redis数据库(服务器地址)
# 一主带多从(可以配置个Redis,写走第一台,读走其他的机器)
'LOCATION': [
'redis://localhost:6379/0',
],
'KEY_PREFIX': 'milky', # 项目名当做文件前缀
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient', # 连接选项(默认,不改)
'CONNECTION_POOL_KWARGS': {
'max_connections': 512, # 连接池的连接(最大连接)
},
}
}
}
@ratelimit(key='ip', rate='5/m', block=True), key=ip means distinguishing by IP, rate=5/m means this endpoint can be requested at most 5 times per minute, block=true means requests exceeding this limit are blocked directly. If the block parameter is not set, exceeding the limit won't block, but you can see the request count in the ratelimit counter.
For more usage, see the official docs: https://django-ratelimit.readthedocs.io/en/stable/index.html
References
- https://github.com/a-roomana/django-multi-captcha-admin
- https://django-simple-captcha.readthedocs.io/en/latest/advanced.html#rendering
Feel free to discuss
I've compiled a series of technical articles and materials. Reply with linux, flutter, c#, netcore, android, java, python, etc. in the backend of the WeChat official account 「程序设计实验室」 to get related technical articles and materials. If you have any questions, you can also leave a message in the official account backend~
_EOF_
Adding CAPTCHA and Multiple Login Attempt Limits to Django-Admin
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
Django过时了吗?从ASGI到AI时代的思考
Django过时?技术趋势变了而已,异步支持短板在AI时代更明显。生态工程化再稳,也挡不住轻量框架和ASGI的冲击。独立开发者该考虑新选择了?
2025-09-12 · Django · 约 1 分钟
使用Django-Channels实现websocket通信+大模型对话
这个只是简单的demo,实际上生产还得考虑很多问题,本文就是为 channels 的应用开了个头,后续有新的研究成果会持续更新博客~
2024-08-14 · Django · 约 1 分钟
Django-Import-Export插件控制数据导入流程
前言 之前写过两篇跟这个插件有关的文章,可以回顾一下: Django数据导入导出神器django-import-export使用 Django-Import-Export插件关于外键的处理 最近有个朋友留言问我一个关于django-import-export插件的问题 为了形象表达这个问题,我举个书籍管理的例子来描述一下 数据库表 | id | name | price | | ---- |
2022-09-02 · Django · 约 1 分钟
Django的单元测试和集成测试
测试,在以前确实是经常被忽略的话题,特别是对于 Python Web 这种快速开发框架
2024-03-06 · Django · 约 1 分钟
讨论
共 0 条加载评论中…