Django默认admin新增登录验证码
Django默认登录只有用户名密码,存在一定安全隐患,想着提高下,用 django-simple-captcha 实现。 1. 安装 django-simple-captcha # 如无 pillow,需安装才可正常使用 # pip install pillow pip install django-simple-captcha 2. 添加应用及配置 # settings INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', # 添加应用 'captcha', ] # 验证码图片宽度/高度 CAPTCHA_IMAGE_SIZE = (100, 40) # 验证码字符长度(数学公式时不生效) CAPTCHA_LENGTH = 4 # 验证码字符类型:字母数字混合(可选值:'numeric'纯数字 / 'alphabetic'纯字母 / 'alphanumeric'混合) CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.random_char_challenge' # 数学公式验证码(替代上述字符验证码) # CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.math_challenge' # 验证码过期时间(秒) CAPTCHA_TIMEOUT = 5 * 60 # 5分钟 # 干扰线数量(0=无干扰线,数值越大干扰越强) CAPTCHA_NOISE_FUNCTIONS = ( 'captcha.helpers.noise_arcs', # 弧形干扰线 'captcha.helpers.noise_dots', # 点状干扰 ) # 验证码背景色(RGB) CAPTCHA_BACKGROUND_COLOR = '#ffffff' # 验证码文字颜色(RGB) CAPTCHA_FOREGROUND_COLOR = '#001100' 3. 执行 python manage.py migrate 4. 新增验证码表单 # 新建 project/forms.py from django import forms from django.contrib.admin.forms import AdminAuthenticationForm from captcha.fields import CaptchaField class AdminCaptchaAuthenticationForm(AdminAuthenticationForm): # 新增验证码字段,label 可自定义显示文本 captcha = CaptchaField(label='验证码') # 保留原有的 admin 登录验证逻辑,仅新增验证码校验 def clean(self): # 先执行父类的 clean 方法(验证用户名密码) cleaned_data = super().clean() # 验证码的校验由 CaptchaField 自动完成,无需额外处理 return cleaned_data 5. 新增视图 # 新建 project/views.py from django.contrib.admin.sites import AdminSite from django.contrib.auth.views import LoginView from .captcha_forms import AdminCaptchaAuthenticationForm class AdminCaptchaLoginView(LoginView): # 指定自定义表单 form_class = AdminCaptchaAuthenticationForm # 复用 admin 登录模板 template_name = 'admin/login.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) admin_site = AdminSite() context.update({ 'site_title': admin_site.site_title, 'site_header': admin_site.site_header, 'site_url': admin_site.site_url, 'title': '管理员登录', }) return context 6. 新增 login.html # 新建 project/codenotes/templates/admin.py <!-- templates/admin/login.html --> {% extends "admin/base_site.html" %} {% load i18n static %} {% block extrastyle %}{{ block.super }} <link rel="stylesheet" href="{% static "admin/css/login.css" %}"> {{ form.media }} <!-- 新增:加载验证码所需的静态资源 --> <style> /* 控制验证码图片垂直对齐,与输入框居中 */ .captcha { vertical-align: middle; margin-bottom: 3px; border: none; } /* 调整验证码输入框的高度,与图片更匹配 */ input[name="captcha_1"] { height: 25px; } </style> {% endblock %} {% block bodyclass %}{{ block.super }} login{% endblock %} {% block nav-breadcrumbs %}{% endblock %} {% block content_title %}{% endblock %} {% block content %} {% if form.errors and not form.non_field_errors %} <p class="errornote"> {% blocktranslate count counter=form.errors.items|length %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktranslate %} </p> {% endif %} {% if form.non_field_errors %} {% for error in form.non_field_errors %} <p class="errornote"> {{ error }} </p> {% endfor %} {% endif %} <div id="content-main"> {% if user.is_authenticated %} <p class="errornote"> {% blocktranslate trimmed %} You are authenticated as {{ username }}, but are not authorized to access this page. Would you like to login to a different account? {% endblocktranslate %} </p> {% endif %} <form action="{{ app_path }}" method="post" id="login-form">{% csrf_token %} <div class="form-row"> {{ form.username.errors }} {{ form.username.label_tag }} {{ form.username }} </div> <div class="form-row"> {{ form.password.errors }} {{ form.password.label_tag }} {{ form.password }} <input type="hidden" name="next" value="{{ next }}"> </div> <!-- 新增:验证码字段渲染 --> <div class="form-row"> {{ form.captcha.errors }} <!-- 验证码错误提示 --> {{ form.captcha.label_tag }} {{ form.captcha }} <!-- 验证码标签 + 输入框 + 图片 --> </div> {% url 'admin_password_reset' as password_reset_url %} {% if password_reset_url %} <div class="password-reset-link"> <a href="{{ password_reset_url }}">{% translate 'Forgotten your password or username?' %}</a> </div> {% endif %} <div class="submit-row"> <input type="submit" value="{% translate 'Log in' %}"> </div> </form> </div> {% endblock %} 7. 添加路由 # urls urlpatterns = [ # 增加路由 path('captcha/', include('captcha.urls')), ] 完成测试看是否成功。