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),如有侵权请告知