上回,上次和大家简单的介绍了下web验证码实现,也说了异步刷新验证码的实现逻辑,不过有些小伙伴还是建议我实现下,废话少说,上代码:此代码是需要依赖:sanic==19.9.0Pillow==7.0.0
篇文章给大家整理的是关于python web框架Flask实现图形验证码的相关知识点,有需要的朋友们参考下。下列代码都是以自己的项目实例讲述的,相关的文本内容很少,主要说明全在代码注释中:
自制图形验证码
这里所说的图形验证码都是自制的图形,通过画布、画笔、画笔字体的颜色绘制而成的。将验证码封装成一个类比较好管理,代码里有绝对详细的注释,当然大家可以直接复制。
里面涉及的字体都是从系统电脑上自带的,大家直接复制当前目录下就可以了。
主目录/utils/captcha/__init__.py
import random
import string
# Image:一个画布
# ImageDraw:一个画笔
# ImageFont:画笔的字体
from PIL import Image, ImageDraw, ImageFont
# Captcha验证码
class Captcha(object):
# 生成4位数的验证码
numbers = 4
# 验证码图片的宽度和高度
size = (100, 30)
# 验证码字体大小
fontsize = 25
# 加入干扰线的条数
line_number = 2
# 构建一个验证码源文本
SOURCE = list(string.ascii_letters)
for index in range(0, 10):
SOURCE.append(str(index))
# 用来绘制干扰线
@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.__gene_random_color(), width=2)
# 用来绘制干扰点
@classmethod
def __gene_points(cls, draw, point_chance, width, height):
# 大小限在【0, 100】中
chance = min(100, max(0, int(point_chance)))
for w in range(width):
for h in range(height):
tmp = random.randint(0, 100)
if tmp > 100 - chance:
draw.point((w, h), fill=cls.__gene_random_color())
# 生成随机颜色
@classmethod
def __gene_random_color(cls, start=0, end=255):
random.seed()
return (random.randint(start, end),
random.randint(start, end),
random.randint(start, end))
# 随机选择一个字体
@classmethod
def __gene_random_font(cls):
fonts = [
"PAPYRUS.TTF",
"CENTAUR.TTF",
"Inkfree.ttf",
"verdana.ttf",
]
font = random.choice(fonts)
return "utils/captcha/"+font
# 用来随机生成一个字符串(包括英文和数字)
@classmethod
def gene_text(cls, numbers):
# numbers是生成验证码的位数
return " ".join(random.sample(cls.SOURCE, numbers))
# 生成验证码
@classmethod
def gene_graph_captcha(cls):
# 验证码图片的宽高
width, height = cls.size
# 创建图片
image = Image.new("RGBA", (width, height), cls.__gene_random_color(0, 100))
# 验证码的字体
font = ImageFont.truetype(cls.__gene_random_font(), cls.fontsize)
# 创建画笔
draw = ImageDraw.Draw(image)
# 生成字符串
text = cls.gene_text(cls.numbers)
# 获取字体的尺寸
font_width, font_height = font.getsize(text)
# 填充字符串
draw.text(((width-font_width)/2, (height-font_height)/2),
text, font=font, fill=cls.__gene_random_color(150, 255))
# 绘制干扰线
for x in range(0, cls.line_number):
cls.__gene_line(draw, width, height)
# 绘制干扰点
cls.__gene_points(draw, 10, width, height)
with open("captcha.png", "wb") as fp:
image.save(fp)
return text, image
一般图形验证码都是在表单中,这样短时间内的数据及建议保存在redis缓存中(用户点击动态刷新图形验证码)。首先我们绘制图形验证码保存到项目的目录下(入口文件是主目录(项目目录)app.py文件,图片也保存到主目录下),然后通过url地址访问自制的图形验证码(这里我只添加主要的代码)显示图形验证码
主目录/common/views.py
@bp.route("/captcha")
def graph_captcha():
"""
使用定义好的图形验证码类,来制作验证码
以验证码为键、验证码为值(为了用户的体验,让其忽略大小写)存储在redis缓存中
通过BytesIO字节流的方式保存和访问图片
:return: 图片响应
"""
# 获取验证码
text, image = Captcha.gene_graph_captcha()
cpcache.set(text.lower(), text.lower())
# BytesIO:字节流
out = BytesIO()
# 保存图片
image.save(out, "png")
# 存储完图片,将文件的指针指向文件头,使下次保存图片能覆盖前面保存的图片,节省空间
out.seek(0)
# 访问图片,并将其作为一个响应返回给前台
resp = make_response(out.read())
resp.content_type = "image/png"
return resp
前端页面的代码如下:
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" name="graph_captcha" placeholder="图形验证码">
<span class="input-group-addon captcha-addon">
<img id="captcha-img" class="captcha-img" src="{{ url_for("common.graph_captcha") }}" alt="">
</span>
</div>
</div>
无非就是再生成一张图形验证码,通过url再次访问就可以,但是这样做是非常麻烦的,这里我很难解释(很难!!!),大家就直接复制代码吧,这个代码就是点击图片生成一个新的url访问图片动态刷新验证码
这个文件放在公共的目录下就可以了
var cpparam = {
setParam: function(href, key, value){
//重新加载整个页面
var isReplaced = false;
var urlArray = href.split("?");
if(urlArray.length > 1){
var queryArray = urlArray[1].split("&");
for(var i=0; i < queryArray.length; i++){
var paramArray = queryArray[i].split("=");
if(paramArray[0] == key){
paramArray[1] = value;
queryArray[i] = paramArray.join("=");
isReplaced = true;
break;
}
}
if(!isReplaced){
var params = {};
params[key] = value;
if(urlArray.length > 1){
href = href + "$" + $.param(params);
}else{
href = href + "?" + $.param(params);
}
}else{
var params = queryArray.join("&");
urlArray[1] = params;
href = urlArray.join("?");
}
}else{
var param = {};
param[key] = value;
if(urlArray.length > 1){
href = href + "$" + $.param(param);
}else{
href = href + "?" + $.param(param);
}
}
return href;
}
};
对应html的js文件就需要实现元素(图片)点击刷新图片,调用上面的变量cpparam生成一章图片并访问。
$(function(){
$("#captcha-img").on("click", function(){
var self = $(this);
var src = self.attr("src");
var newsrc = cpparam.setParam(src, "xx", Math.random());
self.attr("src", newsrc);
});
});
以上就是本次介绍的关于python web框架Flask实现图形验证码全部知识点内容,觉得文章还不错的话不妨点个赞,有任何建议或看法欢迎大家在评论区分享讨论!
我是一名python开发工程师,整理了一套python的学习资料,如果你想提升自己,对编程感兴趣,关注我并在后台私信小编:“08”即可免费领取资料!希望对你能有所帮助!
是个发送验证码时常用的功能,当用户点击【发送验证码】之后出现【重新获取60s后】。在倒计时期间禁止用户继续发送验证码,待倒计时结束之后才可以再次发送验证码。这个可以避免重复发送请求获取多个验证码信息(但是只有最后一次才是有效的),你也不知道自己发送了几次请求,当手机接收到验证码之后容易误以为是正确的验证码。所以做适当的控制是非常有必要的,同时也可以防止恶意发送请求消耗服务器资源。
为了方便这里我们用ElementUI来实现,在el-form-item中利用el-button按钮来实现验证码发送。发送验证码之后直接在el-button上修改现实中在HTML中的【发送验证码】内容,利用disabled属性来控制el-button的是否可以点击。
定义一个retrieve()方法开启倒计时功能,利用setInterval计时器每隔一秒钟调用一次函数,当倒计时结束时通过clearInterval()来关闭计时器。这里我们需要做的是刷新时间和重定义el-button中的HTML内容,disable是用来控制el-button按钮是否可点击的属性。注意:disabled属性别用this.$refs.onConfirm.disbaled=true来定义,会报警告的:Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "disabled"。
在发送之前我们需要对表单中的数据进行校验,这里为什么要嵌套两个validateField呢(validateField支持校验组数)?。因为validateField校验子表单数据时每校验一个值都会返回校验结果,当校验不通过时Error返回值为校验的提示信息,当通过时Error的值为空,所以我们在if语句中用(!Error)表示校验通过。那么这就存在一个问题如果校验数组的话就会进行多次校验,也就会发送多次验证请求。(点一次请求却收到多条验证码这显然是不合理的!)
这里主要的就是retrieve()方法的定义和动态改变HTML内容,可以利用Vue提供的$ref来快速的定位DOM元素实现属性的修改。以上内容是小编给大家分享的【Vue实战088:简单的验证码倒计时功能实现】,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。更多Vue实战技巧可以参考以下专栏:
为了方便学习,下面附上本文用到的源码:
*请认真填写需求信息,我们会在24小时内与您取得联系。