第二节 图形验证码

1、下载第三方图形处理库 pillow

pip install pillow -i https://pypi.douban.com/simple

在这里插入图片描述

2.新建目录及文件

在这里插入图片描述

3.主要内容

在这里插入图片描述

一、展示验证码

1.写图形验证码
# -*- coding: utf-8 -*-
# @Time     : 2021/11/30 18:23
# @Author   : LY
# @Email    : 1540597488@qq.com
# @File     : verifyUtil.py
# @Software : PyCharm
import os
import random
import string

from PIL import Image, ImageFont, ImageDraw, ImageFilter


class ImageVerify:
    """图像验证码类"""

    def __init__(self, length=4, width=140, height=40, size=28):
        """
        初始化图片信息
        :param length: 字符个数
        :param width: 图片宽度
        :param height: 图片高度
        :param size: 字符大小
        """
        self.length = length
        self.width = width
        self.height = height
        self.size = size

    def random_str(self):
        """
        随机字符串
        26大小写字母+10个数字作为数据源(奖池)
        :return:
        """
        source = string.ascii_letters + ''.join(str(i) for i in range(1, 10))
        return ''.join(random.sample(source, self.length))  # 从source中随机获取(self.length)个元素,作为一个片断返回

    def random_color(self, start=0, end=255):
        """
        随机RGB颜色
        :param start:
        :param end:
        :return:
        """
        res = (random.randint(start, end) for i in range(3))  # 返回 (start, end) 之间的任意的3个整数 res为生成器
        return tuple(res)  # 生成器转列表

    def random_lines(self, draw):
        """
        绘制干扰线
        :param draw: 画笔
        :return:
        """
        for i in range(self.length):
            lines = [((random.randint(0, self.width)), (random.randint(0, self.height))) for i in range(2)]
            draw.line(list(lines), fill=self.random_color(64, 250), width=2)

    def rsndom_points(self, draw, rate):
        """
        绘制噪点
        :param draw: 画笔
        :param rate: 频率
        :return:
        """
        for x in range(self.width):
            for y in range(self.height):
                if random.randint(1, 100) <= rate:
                    draw.point((x, y), fill=self.random_color(end=200))

    def verify_code(self):
        """
        生成验证码图片
        :return:
        """
        # 创建画布,Image对象 底图, (0,255) -> (黑,白)
        image = Image.new('RGB', (self.width, self.height), (255, 255, 255))  # (颜色通道,(宽,高),(R,G,B))

        # 创建Font对象
        file_path = os.path.dirname(os.path.abspath(__file__))  # 当前文件的路径
        font = ImageFont.truetype(f'{file_path}/HYYakuHei-85W.ttf', self.size)

        # 创建画笔对象, Draw对象
        draw = ImageDraw.Draw(image)

        self.random_lines(draw)
        self.rsndom_points(draw, 15)

        # 验证码值
        code = self.random_str()

        # 将验证码值绘制到图片中
        for i in range(self.length):
            draw.text((random.randint(35, 40) * i, random.randint(0, 5)), code[i], font=font,
                      fill=self.random_color(35, 150))

        # 模糊滤镜
        image = image.filter(ImageFilter.BLUR)
        return image, code


if __name__ == '__main__':
    imageVerify = ImageVerify()
    image, code = imageVerify.verify_code()
    with open('test.png', 'wb') as fb:
        image.save(fb)  # 传入要保存的文件对象
    print(code)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.实现http请求获取图片
import io

from django.shortcuts import render
from django.http import HttpResponse
from django.views import View

from utils.verifyUtil import ImageVerify


# Create your views here.


class ImageVerifyView(View):
    def get(self, request):
        """获取图片验证码"""
        imageVerify = ImageVerify()
        image, code = imageVerify.verify_code()

        img_bytes = io.BytesIO()
        image.save(img_bytes, format='PNG')
        image_bytes = img_bytes.getvalue()

        return HttpResponse(image_bytes, content_type='image/png')

from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token
from .views import ImageVerifyView
urlpatterns = [
    path('login/', obtain_jwt_token),
    path('image/verification/', ImageVerifyView.as_view()),

]

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、校验验证码

在这里插入图片描述

1. 下载django-redis第三方库
pip install django-redis -i https://pypi.douban.com/simple

在这里插入图片描述

2. 缓存配置,配置使用redis缓存
from config.dbs.redisConfig import LOCATION
# 缓存配置,配置使用redis缓存
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': LOCATION % 0,
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
            'CONNECTION_POOL_KWARGS': {
                "max_connections": 100,
                "decode_response": True
            }
        }
    },
    'verify_codes': {   
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': LOCATION % 1,
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
            'CONNECTION_POOL_KWARGS': {
                "max_connections": 100,
                "decode_responses": True
            }
        }
    }
}
LOCATION = 'redis://127.0.0.1:6379/%d'

在这里插入图片描述

3.储存验证码
import io

from django.shortcuts import render
from django.http import HttpResponse
from django.views import View
from django_redis import get_redis_connection

from config.dbs.redisConfig import LOGIN_KEY_TEMPLATE, EXPIRE_TIME
from utils.verifyUtil import ImageVerify


# Create your views here.


class ImageVerifyView(View):
    def get(self, request, uuid):
        """获取图片验证码"""
        imageVerify = ImageVerify()
        image, code = imageVerify.verify_code()

        img_bytes = io.BytesIO()
        image.save(img_bytes, format='PNG')
        image_bytes = img_bytes.getvalue()

        # 将客户端标识UUID作为key,将验证码答案作为value
        cache = get_redis_connection(alias='verify_codes')  # 使用数据库1作为缓存库
        cache.set(LOGIN_KEY_TEMPLATE % uuid, code, EXPIRE_TIME)

        return HttpResponse(image_bytes, content_type='image/png')

from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token
from .views import ImageVerifyView
urlpatterns = [
    path('login/', obtain_jwt_token),
    path('image/verification/<uuid>/', ImageVerifyView.as_view()),

]
LOCATION = 'redis://127.0.0.1:6379/%d'
LOGIN_KEY_TEMPLATE = 'login:verification:%s'

EXPIRE_TIME = 60*3   # 三分钟过期

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.修改登录权限(校验)
加拦截,验证码不对,就不再返回信息

def jwt_token(token, user=None, request=None):
    """自定义登录成功返回数据处理"""
    param = request.data  # 获取所有的数据
    uuid = param.get('uuid')
    verify = param.get('verify')  # 拿到传入的验证码
    if not uuid or not verify:
        return {'msg': '请输入验证码'}

    # 获取保存的答案
    cache = get_redis_connection(alias='verify_codes')  # 获取Redis连接对象
    redis_verify = cache.get(LOGIN_KEY_TEMPLATE % uuid)
    cache.delete(LOGIN_KEY_TEMPLATE % uuid)
    if not redis_verify:
        return {'msg': '验证码过期'}

    # 传入的验证码和答案进行比较
    if redis_verify.upper() != verify.upper():
        return {'msg': '验证码错误'}

    data = {
        'token': token,
        'username': user.username,
    }

    return data

在这里插入图片描述

情况一:只输入用户名和密码

在这里插入图片描述

情况二:用户名、密码、验证码都输入(已超过三分钟)

在这里插入图片描述

情况三:输入错误验证码

在这里插入图片描述

情况四:用户名、密码、验证码都正确

在这里插入图片描述

三、关于前端页面设计

前端_登录界面设计

说明

教学来源于:码趣教育“一个”老师,源码来源于(https://gitee.com/wuliyige/drfstudy),如有侵权请告知
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YY2065

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值