python web框架Flask实现图形验证码及验证码的动态刷新实例


Posted in Python onOctober 14, 2019

下列代码都是以自己的项目实例讲述的,相关的文本内容很少,主要说明全在代码注释中

自制图形验证码

这里所说的图形验证码都是自制的图形,通过画布、画笔、画笔字体的颜色绘制而成的。将验证码封装成一个类比较好管理,代码里有绝对详细的注释,当然大家可以直接复制。

里面涉及的字体都是从系统电脑上自带的,大家直接复制当前目录下就可以了。

主目录/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_LDA实现方法详解
Oct 25 Python
python flask实现分页的示例代码
Aug 02 Python
Python 经典面试题 21 道【不可错过】
Sep 21 Python
在Python 字典中一键对应多个值的实例
Feb 03 Python
python 通过可变参数计算n个数的乘积方法
Jun 13 Python
python简单鼠标自动点击某区域的实例
Jun 25 Python
elasticsearch python 查询的两种方法
Aug 04 Python
Python解析json代码实例解析
Nov 25 Python
python库skimage给灰度图像染色的方法示例
Apr 27 Python
keras使用Sequence类调用大规模数据集进行训练的实现
Jun 22 Python
如何基于Python Matplotlib实现网格动画
Jul 20 Python
pycharm中选中一个单词替换所有重复单词的实现方法
Nov 17 Python
执行Django数据迁移时报 1091错误及解决方法
Oct 14 #Python
解析Python3中的Import
Oct 13 #Python
Python英文文章词频统计(14份剑桥真题词频统计)
Oct 13 #Python
Python 转换RGB颜色值的示例代码
Oct 13 #Python
Django中自定义查询对象的具体使用
Oct 13 #Python
PyCharm导入python项目并配置虚拟环境的教程详解
Oct 13 #Python
Python 用三行代码提取PDF表格数据
Oct 13 #Python
You might like
深入解析PHP的引用计数机制
2013/06/14 PHP
php socket客户端及服务器端应用实例
2014/07/04 PHP
PHP实现微信小程序人脸识别刷脸登录功能
2018/05/24 PHP
TP5框架简单登录功能实现方法示例
2019/10/31 PHP
JS 添加网页桌面快捷方式的代码详细整理
2012/12/27 Javascript
JS弹出可拖拽可关闭的div层完整实例
2015/02/13 Javascript
在JavaScript应用中使用RequireJS来实现延迟加载
2015/07/01 Javascript
javascript数组排序汇总
2015/07/07 Javascript
javascript实现的闭包简单实例
2015/07/17 Javascript
JS上传组件FileUpload自定义模板的使用方法
2016/05/10 Javascript
js插件dropload上拉下滑加载数据实例解析
2016/07/27 Javascript
vue2.0 实现页面导航提示引导的方法
2018/03/13 Javascript
React 组件中的 bind(this)示例代码
2018/09/16 Javascript
微信开发之企业付款到银行卡接口开发的示例代码
2018/09/18 Javascript
ES6 Proxy实现Vue的变化检测问题
2019/06/11 Javascript
纯js+css实现仿移动端淘宝网站的弹出详情框功能
2019/12/29 Javascript
element 中 el-menu 组件的无限极循环思路代码详解
2020/04/26 Javascript
vue实现自定义多选按钮
2020/07/16 Javascript
[04:55]完美世界副总裁蔡玮:DOTA2的自由、公平与信任
2013/12/18 DOTA
[39:32]2014 DOTA2国际邀请赛中国区预选赛 TongFu VS DT 第二场
2014/05/23 DOTA
python中pygame模块用法实例
2014/10/09 Python
浅谈Python2.6和Python3.0中八进制数字表示的区别
2017/04/28 Python
Python3分析处理声音数据的例子
2019/08/27 Python
python如何使用jt400.jar包代码实例
2019/12/20 Python
python实现替换word中的关键文字(使用通配符)
2020/02/13 Python
Django 项目通过加载不同env文件来区分不同环境
2020/02/17 Python
用CSS3打造HTML5的Logo(实现代码)
2016/06/16 HTML / CSS
汽车专业大学生职业生涯规划范文
2014/01/07 职场文书
阳光体育活动方案
2014/02/16 职场文书
财务部会计岗位职责
2015/02/03 职场文书
庆祝教师节活动总结
2015/03/23 职场文书
MySQL创建索引需要了解的
2021/04/08 MySQL
SpringBoot 集成Redis 过程
2021/06/02 Redis
漫画「日和酱的要求是绝对的」第3卷封面公开
2022/03/21 日漫
MySQL中LAG()函数和LEAD()函数的使用
2022/08/14 MySQL
xhunter1.sys可以删除嘛? win11提示xhunter1.sys驱动不兼容解决办法
2022/09/23 数码科技