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')),
]
完成测试看是否成功。