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-Import-Export插件控制数据导入流程
前言 之前写过两篇跟这个插件有关的文章,可以回顾一下: Django数据导入导出神器django-import-export使用 Django-Import-Export插件关于外键的处理 最近有个朋友留言问我一个关于django-import-export插件的问题 为了形象表达这个问题,我举个书籍管理的例子来描述一下 数据库表 | id | name | price | | ---- |
2022-09-02 · Django · 约 1 分钟
Django-Import-Export插件关于外键的处理
前言 Django-Import-Export是一款很好用很方便的Django数据导出导入插件,可以和DjangoAdmin管理后台完美集成,只需要少量的代码配置即可方便实现你要的多种格式导出导入,关于这个插件的使用更多可以看我之前的文章:这里放文章链接 之前我在使用中都是专门做了一个原始数据的表来存导入的数据,然后再对原始数据表做一些数据处理,把数据存到其他表才能真正使用这些数据。(不是很好的做
2022-04-02 · Django · 约 1 分钟
Django中「强行」使用MVVM设计模式
扫盲 首先带大家了解一下什么是MVVM模式: 什么是MVVM?MVVM是Model-View-ViewModel的缩写。 MVVM是MVC的增强版,实质上和MVC没有本质区别,只是代码的位置变动而已 从名字上看,MVVM比MVC架构中多了一个ViewModel,没错,就是这个ViewModel,他是MVVM相对于MVC改进的核心思想。在开发过程中,由于需求的变更或添加,项目的复杂度越来越高,代码量
2021-12-18 · Django · 约 1 分钟
实测 Django 6.0:模版片段、后台任务、CSP 安全,三大特性体验报告
呵,连WebSocket都没塞进去就敢叫大版本更新?不过模版片段和内置后台任务总算让Django像个现代框架了,至少写HTMX时不用再到处塞碎片文件。原生CSP?早该有了。至于抛弃Python 3.11——跟不上时代的版本留着也是累赘。
2026-01-20 · Django · 约 1 分钟
讨论
共 0 条加载评论中…