83.Django项目中使用验证码
1. 概述
验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序。可以防止:恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试等。
2. 类别
当今验证码各种不同的类别很多,常见的如下:
普通型:随机多个(一般是4个)字母、数字和中文的图片,可能加一些干扰项
问答型:图片中显示一个问题,譬如3+3=?
拖动行为型:拖动一个小图片到一个拼图中
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q9AglfUS-1669135661830)(.\imgs\captcha_drag.jpg)](https://img-blog.csdnimg.cn/737e0f0029bd458ab851e02f4b48d5c2.png)
点击行为型:按照顺序点击图片中的特定位置
3. 实现思路
大部分的验证码验证的思路都是这样的:
- 客户端发送获取验证码的请求
- 服务端接收到验证码请求后,生成对应的验证码和正确答案
- 服务端将验证码的正确答案保存到会话对象当中
- 服务端将验证码返回到客户端
- 客户端看到验证码后:
- 如果看不清等原因,可以重新获取,那么就重新回到第1步
- 正确显示后,输入答案,提交答案到服务端
- 服务端接收到验证码答案后,和保存在会话对象中的正确答案比对,正确就通过验证,失败则返回错误提示
4. Django项目中实现验证码
本文档中以普通的4个字母的验证码作为演示
首先新建项目:captcha_study,子应用:captcha_app。在mysql数据库中新建库catcha_study库。在settings中挂载子应用,配置数据库。然后迁移数据库。创建后台管理superuser用户。以上操作都可以参考本专栏的前几篇文章。
4.1 实现登录功能(未使用验证码)
借用之前 session学习 课程中的部分的登录模块代码
3. settings中配置数据库:
DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql','NAME': 'captcha_study','USER': 'root','PASSWORD': '123456','HOST': '127.0.0.1','PORT': '3306',}}
迁移数据库
由于只使用了django自带的应用的数据库模型,所以直接 migrate 就可以
python manage.py migrate
- 创建 superuser
python manager.py createsuperuser
- 修改主应用的urls.py:
path('captcha/', include('captcha_app.urls')),
- 新增子应用的urls.py
from django.urls import pathfrom . import viewsapp_name = 'captcha_app'urlpatterns = [path('', views.index, name='index'),path('login/', views.login, name='login'),path('logout/', views.logout, name='logout'),]
- views中修改:
from django.contrib import authfrom django.contrib.auth.decorators import login_requiredfrom django.shortcuts import render, redirect# Create your views here.@login_required(login_url='captcha_app:login')def index(request):return render(request, 'captcha_app/index.html')def logout(request):# 登出auth.logout(request)return redirect('captcha_app:login')def login(request):""" 本应用的登录请求登录请求一般有2个不同的http的methodget: 显示的就是登录页面post: 在登录页面输入用户名和密码之后,点击登录提交:param request::return:"""# get请求,对一个 登录的页面if request.method == 'GET':# 通过 session获取 error_messageerror_message = request.session.get('error_message')request.session['error_message'] = Nonereturn render(request, 'captcha_app/login.html', {'error_message':error_message})else:username = request.POST.get('username')password = request.POST.get('password')# 验证用户名和密码user = auth.authenticate(username=username, password=password)# 用户名和密码正确if user:# 使用auth应用的话,登录成功必须调用 login 方法# 在其他 函数中 使用 request.user 获取 用户对象实例auth.login(request, user)return redirect('captcha_app:index')else:# 在不同的 视图函数中传递参数,使用 sessionerror_message = '用户名或者密码错误!!'request.session['error_message'] = error_messagereturn redirect('captcha_app:login')
- 新增template
在子应用中建立 templates 文件夹,再建立一个子文件夹:captcha_app
新增index.html:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>首页</title>
</head>
<body>欢迎光临, 用户:{{ request.user.username }}, email:{{ request.user.email }}<a href="{% url 'captcha_app:logout' %}">退出登录</a>
</body>
</html>
新建login.html:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>登录页面</title><script>function refreshcheckcode(obj) {obj.src = "{% url 'captcha_app:captcha_img' %}?r="+Math.random()console.log(obj.src);}</script>
</head>
<body><form method="post" action="{% url 'captcha_app:login' %}">{% csrf_token %}<table><tr><td>用户名:</td><td><input type="text" value="" name="username" id="username"></td></tr><tr><td>密码:</td><td><input type="password" value="" name="password" id="password"></td></tr><tr><td>验证码:</td><td><input type="text" name="checkbox"><!-- this对象指的就是图片,当点击时,重新获取 --><img src="{% url 'captcha_app:captcha_img' %}" onclick="refreshcheckcode(this);"></td></tr>{% if error_message %}<tr><td colspan="2"><strong>{{ error_message }}</strong></td></tr>{% endif %}<tr><td colspan="2"><input type="submit" value="登录"></td></tr></table></form>
</body>
</html>
4.2 新增图片
安装Pillow库
pip install Pillow==8.3.1
验证码-生成图片
在C盘的Windows中的Fonts选择几款喜欢的字体,放入和captcha.py同一级目录
# captcha_study\common\captcha_4char\captcha.py
import os
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import random
import stringdef random_str(length=4):""" 随机字符串 默认长度 4:param length: 默认长度 4:return:"""return ''.join(random.sample(string.ascii_letters, length))def random_color(s=1, e=255):""" 随机 RGB 颜色:param s: 起始值, 0-255:param e: 结束时, 0-255:return: (r, g, b)"""return random.randint(s, e), random.randint(s, e), random.randint(s, e)def veri_code(length=4, width=160, height=40, size=28):""" 生成验证码图片:param length: 验证码字符串长度:param width: 图片宽度:param height: 图片高度:param size: 字体大小:return: (验证码图片, 验证码字符串)"""# 创建Image对象image = Image.new('RGB', (width, height), (255, 255, 255))# 创建Font对象file = os.path.dirname(os.path.abspath(__file__))font = ImageFont.truetype(f'{file}/common/captcha_4char/simfang.ttf', size)# 创建Draw对象draw = ImageDraw.Draw(image)# 随机颜色填充每个像素for x in range(0, width, 2):for y in range(height):draw.point((x, y), fill=random_color(64, 255))# 验证码code = random_str(length)# 随机颜色验证码写到图片上for t in range(length):draw.text((40 * t + 5, 5), code[t], font=font, fill=random_color(32, 127))# 模糊滤镜image = image.filter(ImageFilter.BLUR)return image, codeif __name__ == '__main__':img, code = veri_code()with open('test.png', 'wb') as f:img.save(f)
views视图
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect, HttpResponse
from captcha_study.common.captcha_4char import captcha
from io import BytesIO
# Create your views here.
@login_required(login_url='captcha_app:login')
def index(request):return render(request, 'captcha_app/index.html')def logout(request):# 登出auth.logout(request)return redirect('captcha_app:login')def login(request):""" 本应用的登录请求登录请求一般有2个不同的http的methodget: 显示的就是登录页面post:在登录页面输入用户名和密码之后,点击登录提交:param request::return:""" # get请求,对一个 登录的页面if request.method == 'GET':# 通过 session获取 error_messageerror_message = request.session.get('error_message')request.session['error_message'] = Nonereturn render(request, 'captcha_app/login.html', {'error_message':error_message})else:username = request.POST.get('username')password = request.POST.get('password')# 获取表单提交的验证码checkcode = request.POST.get('checkbox')print("提交的验证码:",checkcode)# 获取session会话中的checkcodesession_checkcode = request.session.get('checkcode')print("正确的验证码:",session_checkcode)if checkcode and checkcode.lower() == session_checkcode.lower():# 验证用户名和密码user = auth.authenticate(username=username, password=password)# 用户名和密码正确if user:# 使用auth应用的话,登录成功必须调用 login 方法# 在其他 函数中 使用 request.user 获取 用户对象实例auth.login(request, user)return redirect('captcha_app:index')else:# 在不同的 视图函数中传递参数,使用 sessionerror_message = '用户名或者密码错误!!'request.session['error_message'] = error_messagereturn redirect('captcha_app:login')else:# 添加验证码错误信息error_message = '验证码不正确'request.session['error_message'] = error_messagereturn redirect('captcha_app:login') # 不能直接返回模板templates,页面会显示重新提交# 生成验证码,以流文件形式保存
def captcha_img(request):img, code = captcha.veri_code()# 将code保存到session会话中request.session['checkcode'] = code# 创建流文件stream = BytesIO()# 保存到流文件中img.save(stream,'PNG')# 从流文件中获取图片return HttpResponse(stream.getvalue())
urls路由
from django.urls import path
from . import viewsapp_name = 'captcha_app'
urlpatterns = [path('', views.index, name='index'),path('login/', views.login, name='login'),path('logout/', views.logout, name='logout'),path('captcha_img/',views.captcha_img, name='captcha_img'),
]
83.Django项目中使用验证码相关推荐
- Django项目中集成富文本编辑器的通用方法,适合KindEditor,xhEditor,NicEditor,wymeditor等 .
首先,请参考我以前写的一篇博客:如何把nicEditor集成到django中使用 http://blog.csdn.net/huyoo/article/details/4382317 这篇文章中的做法 ...
- django项目中使用crontab定时任务
django项目中使用crontab定时任务 django-crontab 在ubuntu-18.04.2上的使用 需求:django项目中需添加定时任务,定时执行某个函数或者自定义的命令等) 使用步 ...
- 在Django项目中使用富文本编辑器
2019独角兽企业重金招聘Python工程师标准>>> 1 开发要点 现在网上有很多的富文本编辑器,包括Markdown.tinymce.UEditor.KindEditor.cke ...
- Django项目中使用第三方登录——支付宝登录
1. 首先在支付宝开放平台(https://open.alipay.com/platform/home.htm)扫码注册信息 选择开发者中心选择研发服务 配置沙盒应用密钥 使用密钥生成工具生成公钥与私 ...
- Django项目中浏览器显示127.0.0.1拒绝我们的连接请求
在运行Django项目的时候,登录页面已经进去,后面的页面中浏览器却显示127.0.0.1拒绝了我们的连接请求. 解决方法:在settings.py文件里注释掉:django.middleware.c ...
- Celery在Django 项目中如何使用
创建目录celery_pro,并在celery_pro下创建下面两个文件 celery.py # celery.py # -*- coding:utf8 -*- from __future__ imp ...
- python编程django项目中ModuleNotFoundError: No module named ‘django.core.urlresolvers‘解决方法
文章目录 遇到的问题 解决方法 参考 遇到的问题 在做<python编程-从入门到实践>书中的项目的时候,遇到No module named 'django.core.urlresolve ...
- Diango博客--14.使用 Django 项目中的 ORM 编写伪造测试数据脚本
文章目录 0.思路引导 1.脚本目录结构 2.使用 Faker 快速生成测试数据 3.批量生成测试数据 4.执行脚本 5.效果展示 0.思路引导 1)为了防止博客首页展示的文章过多以及提升加载速度,可 ...
- python的django项目中怎么添加app_django下如何创建多个app并设置urls
1.创建第二个app 假设我们项目P下面已经有了一个默认的app,名字是app1.现在我想创建第二个app,名字时app2. 进入pychram下的Terminal中,运行命令:python mana ...
最新文章
- 进程间通信之命名管道
- Jenkins任务失败,发送邮件通知
- Spring系列(四):@Scope注解用法介绍
- uml 类图聚合与组合
- java类成员和实例成员,Java 实例成员和类成员
- mysql sillyr x.so_mysql2.so:libmysqlclient_r.so.15:无法打开共享对象文件:没有这样的文件或目录...
- 网吧IC卡收费系统常见问题与解决(转)
- stm32教程之三重ADC交错采样
- TAOUP初译稿:提交版本
- 网络带宽和下载速度的换算方法
- Java控制树莓派8x8矩阵LED
- 利用css实现太极图的制作(带旋转动画) (课程实践教学项目)
- 使用python库relate搭建LMS学习管理系统
- 坎坎坷坷的深度学习之路(三)-Hello world(2)-------MNIST数据集1-MNIST格式
- Vim 3 vimrc
- linux系统克隆后eth0不见了(IP地址没有了)
- 【buildroot】buildroot的相关make命令
- 怎么给自己的html网页加个密码,密码正确才能显示网页
- Oracle数据库超详细安装教程(含PLSQL),会用电脑就能装!
- postgresql 通过制作函数实现16进制转换为10进制