验证码的开发(自定义)
一、准备工作(在django
中配置redis
的缓存)
1、电脑上安装
redis
brew install redis
2、启动
redis
(启动成功会出现图标)redis-server
3、测试安装是否成功(命令窗口中输入)
redis-cli
4、给
reids
设置密码CONFIG SET requirepass "123456"
5、安装包
pipenv install django-redis
6、在
settings.py
中配置缓存# 配置redis缓存 CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://:[email protected]:6379", # 这里设定了本机的redis数据 # "LOCATION": "redis://127.0.0.1:6379", # 如果redis没设置密码就这样 "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } } }
二、生成随机字符的函数
1、定义一个生成随机字符的函数
import random import string def random_str(num=4): """ 定义一个生产随机字符的函数 :param num: 返回字符多少 :return: """ # string.ascii_letters是生成全部的字符(a-zA-Z) source = list(string.ascii_letters) for index in range(0, 10): source.append(str(index)) return ''.join(random.sample(source, num))
三、单独封装一个工具类用来生成图片验证码
1、安装图片的包
pip install Pillow
2、定义生成验证码的类
import random # 引入绘图的包 from PIL import Image, ImageDraw, ImageFont, ImageFile # 引入缓存的包 from django.core.cache import cache # 引入自定义的生成随机字符的函数 from .random_str import random_str class Captcha(object): """ 定义验证码的类 """ # 选用的字体的路径 font_path = 'Arial.ttf' # 生成几位数的验证码 number = 4 # 生成验证码图片的宽度与高度 size = (100, 30) # 背景颜色,默认是白色 bgcolor = (255, 255, 255) # 字体颜色,默认为蓝色 fontcolor = (random.randint(0, 100), random.randint(0, 100), random.randint(0, 100)) # 验证码字体大小 fontsize = 25 # 干扰线的颜色,默认是红色 linecolor = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) # 是否要加入干扰线 draw_line = True # 是否绘制干扰点 draw_point = True # 加入干扰线的条数 line_number = 2 # 定义一个类方法绘制干扰线 @classmethod def __gene_line(cls, draw, width, height): # 开始位置 begin = (random.randint(0, width), random.randint(0, height)) # 结束位置 end = (random.randint(0, width), random.randint(0, height)) draw.line([begin, end], fill=cls.linecolor) # 定义一个类方法绘制干扰点 @classmethod def __gene_points(cls, draw, point_chance, width, height): chance = min(100, max(0, int(point_chance))) # 大小限制在[0, 100] for w in range(width): for h in range(height): tmp = random.randint(0, 100) if tmp > 100 - chance: draw.point((w, h), fill=(0, 0, 0)) # 生成验证码 @classmethod def gene_code(cls): width, height = cls.size # 宽和高 image = Image.new('RGBA', (width, height), cls.bgcolor) # 创建图片 font = ImageFont.truetype(cls.font_path, cls.fontsize) # 验证码的字体 draw = ImageDraw.Draw(image) # 创建画笔 text = random_str(4) # 生成字符串 font_width, font_height = font.getsize(text) draw.text(((width - font_width) / 2, (height - font_height) / 2), text, font=font, fill=cls.fontcolor) # 填充字符串 # 如果需要绘制干扰线 if cls.draw_line: # 遍历line_number次,就是画line_number根线条 for x in range(0, cls.line_number): cls.__gene_line(draw, width, height) # 如果需要绘制噪点 if cls.draw_point: cls.__gene_points(draw, 10, width, height) # 保存到缓存中,过期时间为2分钟 cache.set(text.lower(), text.lower(), 120) return (text, image) # 验证验证码 @classmethod def check_captcha(cls, captcha): captcha_cache = cache.get(captcha) if captcha_cache and captcha_cache == captcha: # 删除缓存 cache.delete(captcha) return True else: return False
四、视图的书写
1、导包
from io import BytesIO from django.shortcuts import HttpResponse from django.views.generic import View # 引入生成验证码的类 from utils.captcha import Captcha
2、视图类使用
BytesIO
返回图片class CaptchaView(View): """ 定义一个图片验证码的视图 """ def get(self, request, *args, **kwargs): text, image = Captcha.gene_code() out = BytesIO() image.save(out, 'png') out.seek(0) # 设置返回请求头 response = HttpResponse(content_type='image/png') response.write(out.read()) return response
五、配置url
及浏览访问
1、
url
的配置from django.urls import path from .views import login, register, captcha urlpatterns = [ ... path('captcha/', captcha.CaptchaView.as_view(), name='captcha') ]
2、浏览器中访问
六、校验验证码的合法性
1、还是使用用户注册的时候添加一个验证码
2、在
forms.py
中校验用户输入的验证码合法性from utils.captcha import Captcha class RegisterForm(forms.Form): """ 用户注册的form """ email = forms.EmailField(required=True, error_messages={'required': '用户名不能为空'}) password = forms.CharField(required=True, min_length=5, error_messages={'required': '密码不能为空', 'min_length': '密码长度太短'}) captcha = forms.CharField(max_length=4, min_length=4) def clean_captcha(self): # 获取用户输入的验证码 captcha = self.cleaned_data.get('captcha', None) if Captcha.check_captcha(captcha=captcha): return captcha else: raise forms.ValidationError('验证码错误')
3、前端用户点击验证码切换
$('#captcha').on('click', function () { var base_url = $(this).attr('src').split('?')[0]; var new_url = `${base_url}?${+new Date()}`; $(this).attr('src', new_url); })