83.Django项目中使用验证码

news2025/2/23 18:32:02

1. 概述

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

2. 类别

​ 当今验证码各种不同的类别很多,常见的如下:

  1. 普通型:随机多个(一般是4个)字母、数字和中文的图片,可能加一些干扰项

  2. 问答型:图片中显示一个问题,譬如3+3=?

  3. 拖动行为型:拖动一个小图片到一个拼图中

    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q9AglfUS-1669135661830)(.\imgs\captcha_drag.jpg)](https://img-blog.csdnimg.cn/737e0f0029bd458ab851e02f4b48d5c2.png)

  4. 点击行为型:按照顺序点击图片中的特定位置

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZuwelXqX-1669135661832)(.\imgs\captcha_click.jpg)]

3. 实现思路

​ 大部分的验证码验证的思路都是这样的:

  1. 客户端发送获取验证码的请求
  2. 服务端接收到验证码请求后,生成对应的验证码和正确答案
  3. 服务端将验证码的正确答案保存到会话对象当中
  4. 服务端将验证码返回到客户端
  5. 客户端看到验证码后:
    • 如果看不清等原因,可以重新获取,那么就重新回到第1步
    • 正确显示后,输入答案,提交答案到服务端
  6. 服务端接收到验证码答案后,和保存在会话对象中的正确答案比对,正确就通过验证,失败则返回错误提示

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',
       }
   }
  1. 迁移数据库

    由于只使用了django自带的应用的数据库模型,所以直接 migrate 就可以

   python manage.py migrate
  1. 创建 superuser
   python manager.py createsuperuser
  1. 修改主应用的urls.py:
   path('captcha/', include('captcha_app.urls')),
  1. 新增子应用的urls.py
   from django.urls import path
   from . import views
   
   app_name = 'captcha_app'
   
   urlpatterns = [
       path('', views.index, name='index'),
       path('login/', views.login, name='login'),
       path('logout/', views.logout, name='logout'),
   ]
  1. views中修改:
   from django.contrib import auth
   from django.contrib.auth.decorators import login_required
   from 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的method
           get: 显示的就是登录页面
           post: 在登录页面输入用户名和密码之后,点击登录提交
   
       :param request:
       :return:
       """
       # get请求,对一个 登录的页面
       if request.method == 'GET':
           # 通过 session获取 error_message
           error_message = request.session.get('error_message')
           request.session['error_message'] = None
           return 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:
               # 在不同的 视图函数中传递参数,使用 session
               error_message = '用户名或者密码错误!!'
               request.session['error_message'] = error_message
               return redirect('captcha_app:login')
  1. 新增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 string

def 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, code

if __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的method
        get: 显示的就是登录页面
        post:在登录页面输入用户名和密码之后,点击登录提交

    :param request:
    :return:
    """	
    # get请求,对一个 登录的页面
    if request.method == 'GET':
        # 通过 session获取 error_message
        error_message = request.session.get('error_message')
        request.session['error_message'] = None
        return 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会话中的checkcode
        session_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:
                # 在不同的 视图函数中传递参数,使用 session
                error_message = '用户名或者密码错误!!'
                request.session['error_message'] = error_message
                return redirect('captcha_app:login')
        else:
            # 添加验证码错误信息
            error_message = '验证码不正确'
            request.session['error_message'] = error_message
            return 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 views

app_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'),
]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/28823.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分布式节能聚类算法(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

MySQL隔离级别的底层理解(MVCC+锁)

MySQL事务的隔离级别和并发的关系 mysql是一个C/S架构的软件, 也就意味着, 同一个mysql服务器可能同时存在很多的clients集合来访问. 此时最重要的是什么? 并发性. 并发时候的安全. 并发和数据库安全性本来就是相互矛盾的。要保证更好的安全性最好的方式是什么? 完全舍弃并…

云原生系列 四【轻松入门容器基础操作】

✅作者简介&#xff1a; CSDN内容合伙人&#xff0c;全栈领域新星创作者&#xff0c;阿里云专家博主&#xff0c;华为云云 享专家博主&#xff0c;掘金后端评审团成员 &#x1f495;前言&#xff1a; 最近云原生领域热火朝天&#xff0c;那么云原生是什么&#xff1f;何为云原生…

最详细的Keycloak教程:Keycloak实现手机号、验证码登陆——(一)Keycloak的下载与使用

目录一、 简介二、Keycloak下载与启动三、配置国际化内容一、 简介 接触keycloak已经半个多月了&#xff0c;主要是为了用来集成现已有的项目&#xff0c;也是弄得头大&#xff0c;代码不负脱发人&#xff0c;也是有点小成果了&#xff0c;在这里把自己的这点小小经验分享给大…

CMOS IC功耗类型及其影响因素

目录 概述 开关功耗&#xff08;Switch Power&#xff09; 内部功耗&#xff08;Internal Power&#xff09; 漏电功耗&#xff08;Leakage Power&#xff09; 工艺库相关 开关功率相关信息 内部功耗相关信息 漏电功耗相关信息 例子 概述 该部分对IC功耗的类型进行介绍 先总体来…

安装黑苹果常见问题总结

黑苹果字体模糊&#xff1f; 由于macOS使用了HiDPi技术以达到更高的每英寸像素率&#xff0c;即缩放&#xff0c;因此普通显示器只要不是4k分辨率&#xff0c;安装黑苹果后一定会遇到字体模糊的问题&#xff0c;解决方法可以阅读我往期发布的文章。 为什么用iStat Menus无法检…

期末前端web大作业:用DIV+CSS技术设计的动漫网站——火影忍者6页 带报告

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材&#xff0c;DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 网页设计作业 | 动漫网页设计 | 动漫网页设计成品 | 动漫网页设计成品模板 | 简单漫画网页设计成品 | HTML期末大学生网页设计作业 HTML&#xff1a;结…

深度学习第四课——卷积神经网络(week 1)

目录 一、前言 1.1 卷积 1.2 其他滤波器 1.3 Padding 1.3.1 解释 1.3.2 填充多少像素的选择 1.4 卷积步长 1.5 三维卷积 1.6 单层卷积网络 1.7 深度卷积神经网络的一个示例 1.8 池化层 1.8.1 最大池化 1.8.2 平均池化 1.8.3 总结 1.9 卷积神经网络示例 1.10 为…

23种设计模式

1.创建型模式 ① 创建型模式的作用就是创建对象&#xff0c;说到创建一个对象&#xff0c;最熟悉的就是 new 一个对象&#xff0c;然后 set 相关属性 ② 但是很多场景下&#xff0c;需要给客户端提供更加友好的创建对象的方式&#xff0c;尤其是那种我们定义了类&#xff0c;但…

leetcode:644. 子数组最大平均数 II【浮点数二分 + 子数组最大平均值技巧】

目录题目截图题目分析ac code总结题目截图 题目分析 枚举铁超时&#xff0c; 10 ** -5考虑二分平均值需要同时考虑总和和长度能否只考虑一个考虑每个数num’ num - avg这样可以忽略长度猜一个guess_avg是否可能达到num’ -> num - avg_guess区间sum(num’) > 0说明其真…

Linux 开机运行sh 脚本 三种方法

一、修改开机启动文件​​​​​​​ /etc/rc.local&#xff08;或者/etc/rc.d/rc.local&#xff09; 1、编辑rc.local文件&#xff08;命令后面让得加&号&#xff0c;表示后台运行&#xff09; 2、最后修改rc.local文件的执行权限&#xff1a; chmod x /etc/rc.local二…

实践历练的力量

要让你的屁股和椅子建立起深刻的友谊来&#xff0c;要坚持下来。 掌握知识离不开实践和做&#xff0c;只有经历了这样的过程才能将知识转换为自己的。也才能真正明白在什么环境下需要什么样的知识。 解决问题。 真正的学习一定包括实践&#xff0c;而实践是更重要的学习。学…

【sfu】接收侧拼装H264 帧后的回调流程

sfu 基于webrtc协议栈,【sfu】rtc 入口 预先分配了资源,并创建了adpter模块和call模块。【webrtc】rtp包组帧 :涉及到收到rtp包到组帧、传递给Frame处理直到解码器的流程。帧就是从解码器导出的。我们只需要注册1个外部解码器就可以拿到编码后的H264 帧,给到其他流程处理。接…

【JVS低代码开发平台】支持纯手工配置的数据加工、处理、展现的数据仓库

数据智仓英文名称为Smart Data Warehouse&#xff0c;可简写为SDW。数据智仓是JVS整体企业数字化解决方案的核心能力&#xff0c;与JVS的低代码开发套件平级&#xff0c;如下图所示&#xff1a; 数据仓库的目的是构建面向分析的集成化数据环境&#xff0c;为企业提供基于数据的…

SOLIDWORKS 2023新功能揭秘!升级版轻松找到材料明细表修改

SOLIDWORKS 2023版本已经与大家见面&#xff0c;今天众联亿诚继续和大家分享SOLIDWORKS 2023 工程图的亮点新功能之一&#xff1a;材料明细表的覆盖。 材料明细表的覆盖 SOLIDWORKS工程图是我们常用的功能之一。当采用断开链接模式修改材料明细表的内容时&#xff0c;修改的内容…

【强化学习论文合集】AAAI-2022 强化学习论文 | 2022年合集(二)

强化学习(Reinforcement Learning, RL),又称再励学习、评价学习或增强学习,是机器学习的范式和方法论之一,用于描述和解决智能体(agent)在与环境的交互过程中通过学习策略以达成回报最大化或实现特定目标的问题。 本专栏整理了近几年国际顶级会议中,涉及强化学习(Rein…

【web前端期末大作业】HTML+CSS宠物狗静态网页设计

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

2.18 小红书的表情文案一键生成,原来这么简单【玩赚小红书】

想知道小红书的表情文案是怎么生成的&#xff0c;比如这种&#xff1a; 情人节走心 高调仪式感浪漫小 机&#xff01; 式秀恩爱&#xff0c;不如比比谁更走心&#xff01;❤️ EVERYDAY7️⃣彩⭐期裤 高浓度释放爱意讯号~ 今年情 节&#xff0c;大胆直接的爱意让他抱个 怀&…

【爬虫】Python爬取世界杯球员榜单并保存到excel经验分享

大家好 我是Yhen 今天给大家分享一下 如何爬取卡塔尔世界杯球员榜 数据来源&#xff1a;百度体育 https://tiyu.baidu.com/match/%E4%B8%96%E7%95%8C%E6%9D%AF/tab/%E7%90%83%E5%91%98%E6%A6%9C/current/0 文章目录一.需求分析二.思路分析三.代码实战四.源码获取一.需求分析…

XSS game -xss学习

网址 https://xss-game.appspot.com/level1Level 1: Hello, world of XSS payload: <script> alert(1); </script>漏洞产生处: message "Sorry, no results were found for <b>" query "</b>."Level 2: Persistence is key…