0
点赞
收藏
分享

微信扫一扫

ThingsBoard Edge 设备连接

一葉_code 2024-03-16 阅读 13

Django之图形验证码

目录

【1】静态图片

最基础的生成图片就是获取静态文件

<div style="margin-left: 10px;">
    <img src="{% static 'img/img.png' %}" width="100%" height="37px">
</div>

image-20240315161835853

【2】视图层绑定静态文件

# urls.py
path('get_verify_img/', views.get_verify_img, name='get_verify_img'),
# views.py
import os
from django.conf import settings

def get_verify_img(request):
    img_path = os.path.join(settings.BASE_DIR, 'Blog/static/img/img3.png')
    with open(img_path, 'rb') as f:
        data = f.read()
    return HttpResponse(data)
<img src="{% url 'Blog:get_verify_img' %}" width="100%" height="37px">

image-20240315175632902

【3】PIL生成图片(固定背景)

安装Pillow模块

pip install Pillow

导入

from PIL import Image, ImageDraw, ImageFont

# Image:负责生成图片数据
# ImageDraw:在生成的图片上面添加相应数据
# ImageFont:添加相应数据时指定字体样式、大小、间距
from PIL import Image, ImageDraw, ImageFont

def get_verify_img(request):
    # 图片名称
    img_name = 'verify.png'

    # 指定图像模式
    mode = 'RGB'
    # 指定图像尺寸
    size = (123, 37)
    # 指定图像颜色(颜色名或三原色盘)
    color = 'blue'
	
    # 创建图片对象
    img_obj = Image.new(mode=mode, size=size, color=color)

    # 设置图片保存路径
    img_path = os.path.join(settings.BASE_DIR, 'Blog/static/img', img_name)
    # 保存图片
    img_obj.save(img_path)
	
	# 读取图片
    with open(img_path, 'rb') as f:
        data = f.read()
    return HttpResponse(data)

image-20240315193050165

【4】将图片存储在内存

要将数据临时存储在内存需要借助Python的IO模块

from io import BytesIO, StringIO
# BytesIO:负责临时存储数据
# StringIO:负责取出数据

顺便把随机颜色做了

def random_rgb():
    return random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)
def get_verify_img(request):
    img_name = 'verify.png'

    # 指定图像模式
    mode = 'RGB'
    # 指定图像尺寸
    size = (123, 37)
    # 随机生成图像颜色
    color = random_rgb()

    img_obj = Image.new(mode=mode, size=size, color=color)

    # 创建存储内存空间
    io_obj = BytesIO()
    
    # 保存图片并指定后缀
    img_obj.save(io_obj, 'png')
    
    # 取出图片
    data = io_obj.getvalue()

    return HttpResponse(data)

【5】生成文本信息

先生成一个随机的五位数文本

def random_word():
    # 0-9数字
    random_num = random.randint(0, 9)
    # a-z
    random_lower = chr(random.randint(97, 122))
    # A-Z
    random_upper = chr(random.randint(65, 90))
    word = random.choice([random_upper, random_lower, str(random_num)])
    return word
def get_verify_img(request):
    img_name = 'verify.png'

    # 指定图像模式
    mode = 'RGB'
    # 指定图像尺寸
    size = (123, 50)
    # 随机生成图像颜色
    color = random_rgb()

    img_obj = Image.new(mode=mode, size=size, color=color)

    # 创建画笔对象
    img_draw = ImageDraw.Draw(img_obj)
    
    # 设置字体和大小
    img_font = ImageFont.truetype('Blog/static/font/TianShiBaoDiaoTiJian-1.ttf', 34)

    code = ''
    for i in range(0, 4):
        word = random_word()
        # text依次放入参数(坐标,文本内容,字体颜色,字体样式)
        img_draw.text((i * 15 + 20, 4), word, random_rgb(), img_font)
        code += word

        # 创建存储内存空间
        io_obj = BytesIO()
        
        # 保存图片并指定后缀
        img_obj.save(io_obj, 'png')
        
        # 取出图片
        data = io_obj.getvalue()
    return HttpResponse(data)

实例效果

image-20240315221303849

【6】实现图片刷新

首先需要知道刷新图片的原理

当这种验证图片数据在开发者模式中将它的末尾添加?并加入任意数字后按下回车他就会自动变换

http://127.0.0.1:8000/Blog/get_verify_img/

image-20240315220940213

image-20240315221005599

<img src="{% url 'Blog:get_verify_img' %}" width="100%"
	height="37px" id="img_verify" alt="">

<script>
     const verify = document.getElementById('img_verify')
    verify.addEventListener('click', function () {
        // 获取原始的 src 属性值
        const verify_src = verify.src;
        // 检查原始 src 是否已经包含时间戳
        if (verify_src.includes('?')) {
            // 如果已经包含时间戳,只替换最后一个时间戳
            verify.src = verify_src.replace(/\?.*$/, '') + '?' + new Date().getTime();
        } else {
            // 如果原始 src 没有时间戳,直接添加时间戳
            verify.src = verify_src + '?' + new Date().getTime();
        }
    })
</script>

后端将生成图片验证码拆分到新的文件

import random

from PIL import Image, ImageDraw, ImageFont
from io import BytesIO, StringIO


def random_rgb():
    return random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)


def random_word():
    # 0-9数字
    random_num = random.randint(0, 9)
    # a-z
    random_lower = chr(random.randint(97, 122))
    # A-Z
    random_upper = chr(random.randint(65, 90))
    word = random.choice([random_upper, random_lower, str(random_num)])
    return word


def verify():
    img_name = 'verify.png'
    data = None
    # 指定图像模式
    mode = 'RGB'
    # 指定图像尺寸
    size = (100, 50)
    # 随机生成图像颜色
    color = random_rgb()

    img_obj = Image.new(mode=mode, size=size, color=color)

    img_draw = ImageDraw.Draw(img_obj)
    img_font = ImageFont.truetype('Blog/static/font/TianShiBaoDiaoTiJian-1.ttf', 35)

    code = ''
    words = ''
    for i in range(0, 4):
        word = random_word()
        # text依次放入参数(坐标,文本内容,字体颜色,字体样式)
        img_draw.text((i * 15 + 20, 4), word, random_rgb(), img_font)
        code += word

        # 创建存储内存空间
        io_obj = BytesIO()

        # 保存图片并指定后缀
        img_obj.save(io_obj, 'png')

        # 取出图片
        data = io_obj.getvalue()

        words += word
    print(words)
    # 返回图片数据,验证码文本
    return data,words

视图层代码

# 文件路径自定义
from lib.verify_img.verify import verify

def get_verify_img(request):
    data, words = verify()
    print(words)
    return HttpResponse(data)
举报

相关推荐

0 条评论