Django图片验证码

本文介绍如何在Django项目中使用第三方库django-simple-captcha来实现图形验证码功能,包括安装配置、表单集成及前端展示等步骤。

 图片验证码
 

为了防止机器人频繁登录网站或者破坏分子恶意登录,很多用户登录和注册系统都提供了图形验证码功能。

验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序。可以防止恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试。

图形验证码的历史比较悠久,到现在已经有点英雄末路的味道了。因为机器学习、图像识别的存在,机器人已经可以比较正确的识别图像内的字符了。但不管怎么说,作为一种防御手段,至少还是可以抵挡一些低级入门的攻击手段,抬高了攻击者的门槛。

在Django中实现图片验证码功能非常简单,有现成的第三方库可以使用,我们不必自己开发(也要能开发得出来,囧)。这个库叫做django-simple-captcha。

一、安装captcha
在Pycharm的terminal中,首先进入mysite_env虚拟环境,然后安装第三方库:

执行命令:pip install django-simple-captcha
(mysite_env) F:\Django_course\mysite_env\Scripts>pip install django-simple-captcha
Collecting django-simple-captcha
  Downloading django-simple-captcha-0.5.5.zip (144kB)
    100% |████████████████████████████████| 153kB 139kB/s                                                              
Requirement already satisfied: setuptools in f:\django_course\mysite_env\lib\site-packages (from django-simple-captcha)
Collecting six>=1.2.0 (from django-simple-captcha)
  Downloading six-1.11.0-py2.py3-none-any.whl
Requirement already satisfied: Django>=1.7 in f:\django_course\mysite_env\lib\site-packages (from django-simple-captcha)
Collecting Pillow>=2.2.2 (from django-simple-captcha)
  Downloading Pillow-4.3.0-cp36-cp36m-win_amd64.whl (1.5MB)
    100% |████████████████████████████████| 1.5MB 364kB/s                                                              
Requirement already satisfied: pytz in f:\django_course\mysite_env\lib\site-packages (from Django>=1.7->django-simple-captcha)
Collecting olefile (from Pillow>=2.2.2->django-simple-captcha)
Building wheels for collected packages: django-simple-captcha
  Running setup.py bdist_wheel for django-simple-captcha ... done
  Stored in directory: C:\Users\Administrator\AppData\Local\pip\Cache\wheels\f2\a1\ce\6eddab991940a2502d2252870ce5870388ac085e9508bcc2cb
Successfully built django-simple-captcha
Installing collected packages: six, olefile, Pillow, django-simple-captcha
Successfully installed Pillow-4.3.0 django-simple-captcha-0.5.5 olefile-0.44 six-1.11.0
Django自动帮我们安装了相关的依赖库six、olefile和Pillow,其中的Pillow是大名鼎鼎的绘图模块。

二、注册captcha
在settings中,将‘captcha’注册到app列表里:

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'login',
    'captcha',
]
captcha需要在数据库中建立自己的数据表,所以需要执行migrate命令生成数据表:

(mysite_env) F:\Django_course\mysite>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, captcha, contenttypes, login, sessions
Running migrations:
  Applying captcha.0001_initial... OK
三、添加url路由
在根目录下的urls.py文件中增加captcha对应的网址:

from django.conf.urls import url
from django.conf.urls import include
from django.contrib import admin
from login import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),
    url(r'^login/', views.login),
    url(r'^register/', views.register),
    url(r'^logout/', views.logout),
    url(r'^captcha', include('captcha.urls'))  # 增加这一行
]
由于使用了二级路由机制,需要在顶部from django.conf.urls import include。

四、修改forms.py
如果上面都OK了,就可以直接在我们的forms.py文件中添加CaptchaField了。

from django import forms
from captcha.fields import CaptchaField

class UserForm(forms.Form):
    username = forms.CharField(label="用户名", max_length=128, widget=forms.TextInput(attrs={'class': 'form-control'}))
    password = forms.CharField(label="密码", max_length=256, widget=forms.PasswordInput(attrs={'class': 'form-control'}))
    captcha = CaptchaField(label='验证码')
注意需要提前导入from captcha.fields import CaptchaField,然后就像写普通的form字段一样添加一个captcha字段就可以了!

五、修改login.html
由于我们前面是手动生成的form表单,所以还要修改一下,添加captcha的相关内容,如下所示:

{% extends 'base.html' %}
{% load staticfiles %}
{% block title %}登录{% endblock %}
{% block css %}<link href="{% static 'css/login.css' %}" rel="stylesheet"/>{% endblock %}


{% block content %}
    <div class="container">
        <div class="col-md-4 col-md-offset-4">
          <form class='form-login' action="/login/" method="post">

              {% if message %}
                  <div class="alert alert-warning">{{ message }}</div>
              {% endif %}
              {% csrf_token %}
              <h2 class="text-center">欢迎登录</h2>
              <div class="form-group">
                  {{ login_form.username.label_tag }}
                  {{ login_form.username}}
              </div>
              <div class="form-group">
                  {{ login_form.password.label_tag }}
                  {{ login_form.password }}
              </div>

              <div class="form-group">
                  {{ login_form.captcha.errors }}
                  {{ login_form.captcha.label_tag }}
                  {{ login_form.captcha }}
              </div>

              <button type="reset" class="btn btn-default pull-left">重置</button>
              <button type="submit" class="btn btn-primary pull-right">提交</button>

          </form>
        </div>
    </div> <!-- /container -->
{% endblock %}
这里额外增加了一条{{ login_form.captcha.errors }}用于明确指示用户,你的验证码不正确。

六、查看效果
重启服务器,进入登录页面,尝试用用户名错误、密码不对、验证码不对、全对的不同情况,看看我们新增的四位验证码的效果如何。

33.png-29.8kB

就是这么简单!我们加入了一个防止机器人或者恶意登录的图形验证码功能,虽然界面难看了点,但底子是好的,你可以根据需要进行美化。其中验证图形码是否正确的工作都是在后台自动完成的,只需要使用is_valid()这个forms内置的验证方法就一起进行了,完全不需要在视图函数中添加任何的验证代码,非常方便快捷!

关于captcha的功能,当然绝不仅限于此,你可以设置六位、八位验证码,可以对图形噪点的生成模式进行定制,这些就留待你自己学习和研究了。

### Django 图片验证码不显示的原因分析与解决方案 #### 可能原因及对应解决方法: 1. **Redis配置问题** 如果 Redis 数据库未正确配置,可能导致验证码无法存储或读取失败。确保 `dev.py` 文件中的 Redis 配置指向正确的数据库编号,并确认 Redis 服务已启动并正常运行[^3]。 ```python CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/2", # 确认此处的数据库编号为2 "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } }, "verify_code": { # 验证码专用缓存 "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/2", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } } } ``` 2. **视图逻辑错误** 在 `ImageCodeView` 类中,如果生成的验证码未能正确写入 Redis 或返回给前端,则可能引发图片不显示的问题。需检查以下代码片段是否按预期执行[^1]。 ```python from django_redis import get_redis_connection class ImageCodeView(View): def get(self, request, uuid): text, image = captcha.generate_captcha() redis_conn = get_redis_connection('verify_code') redis_conn.setex(f'img_{uuid}', 300, text) # 存储验证码至Redis,有效期5分钟 return http.HttpResponse(image, content_type='image/png') ``` 3. **静态资源路径设置不当** 若项目的静态资源配置有误,可能会导致图片验证码加载失败。建议检查 `settings.py` 中关于静态文件的相关配置,尤其是 `STATIC_URL` 和 `MEDIA_ROOT` 的设定[^4]。 ```python STATIC_URL = '/static/' MEDIA_URL = '/media/' # 如果涉及媒体文件上传 MEDIA_ROOT = os.path.join(BASE_DIR, 'media') ``` 4. **Nginx代理拦截问题** 当使用 Nginx 进行反向代理时,若其默认行为会拦截某些 HTTP 响应状态码(如 500),则可能导致验证码请求被中断。可以通过调整 Nginx 配置来避免此类情况发生[^2]。 ```nginx server { ... location / { proxy_intercept_errors off; # 关闭错误页面替换功能 proxy_pass http://django_app; } } ``` 5. **浏览器缓存影响** 用户刷新页面后仍看到旧版验证码可能是由于浏览器缓存所致。可通过修改 URL 参数的方式强制重新获取新验证码[^5]。 ```javascript $('#id_img').click(function () { let oldSrc = $(this).attr('src'); $(this).attr('src', `${oldSrc}?t=${new Date().getTime()}`); }); ``` --- ### 示例代码:Vue 实现动态更新验证码 以下是基于 Vue.js 动态更换验证码的一个简单例子[^3]。 ```html <template> <div> <img :src="captchaUrl" @click="refreshCaptcha"> </div> </template> <script> export default { data() { return { captchaUrl: "/api/image-code/?uuid=abc" }; }, methods: { refreshCaptcha() { this.captchaUrl += "?_t=" + new Date().getTime(); } } }; </script> ``` --- ### 总结 上述方案涵盖了从后端到前端可能出现的各种问题及其对应的修复措施。实际操作过程中可根据具体环境逐一排查直至解决问题。 问题
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值