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之开始真正编程
Sep 12 Python
python分析网页上所有超链接的方法
May 08 Python
python使用TensorFlow进行图像处理的方法
Feb 28 Python
解决python爬虫中有中文的url问题
May 11 Python
Python 面试中 8 个必考问题
Nov 16 Python
Python字符串逆序输出的实例讲解
Feb 16 Python
Python 实现Serial 与STM32J进行串口通讯
Dec 18 Python
django model 条件过滤 queryset.filter(**condtions)用法详解
May 20 Python
如何使用Cython对python代码进行加密
Jul 08 Python
Django ModelForm组件原理及用法详解
Oct 12 Python
python实现三种随机请求头方式
Jan 05 Python
Python中的pprint模块
Nov 27 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实现最简单的MVC框架实例教程
2014/09/08 PHP
php实现的网络相册图片防盗链完美破解方法
2015/07/01 PHP
PHP实现的方程求解示例分析
2016/11/11 PHP
tp5框架使用cookie加密算法实现登录功能示例
2020/02/10 PHP
php设计模式之原型模式分析【星际争霸游戏案例】
2020/03/23 PHP
使用JQuery和CSS模拟超链接的用户单击事件的实现代码
2012/05/23 Javascript
js实现点击注册按钮开始读秒倒计时的小例子
2013/05/11 Javascript
Iframe实现跨浏览器自适应高度解决方法
2014/09/02 Javascript
实例分析javascript中的call()和apply()方法
2014/11/28 Javascript
基于HTML+CSS,jQuery编写的简易计算器后续(添加了键盘监听)
2016/01/05 Javascript
JQuery的Pager分页器实现代码
2016/05/03 Javascript
jQuery Pagination分页插件_动力节点Java学院整理
2017/07/17 jQuery
解决微信二次分享不显示摘要和图片的问题
2017/08/18 Javascript
node.js+express+mySQL+ejs+bootstrop实现网站登录注册功能
2018/01/12 Javascript
vue中element组件样式修改无效的解决方法
2018/02/03 Javascript
jQuery中的$是什么意思及 $. 和 $().的区别
2018/04/20 jQuery
JavaScript常用截取字符串的三种方式用法区别实例解析
2018/05/15 Javascript
Vue 获取数组键名的方法
2018/06/21 Javascript
JavaScript学习笔记之DOM基础操作实例小结
2019/01/09 Javascript
JS实现的点击按钮图片上下滚动效果示例
2019/01/28 Javascript
Vue CLI3基础学习之pages构建多页应用
2019/06/02 Javascript
vue中使用element ui的弹窗与echarts之间的问题详解
2019/10/25 Javascript
vue移动端使用appClound拉起支付宝支付的实现方法
2019/11/21 Javascript
python实现监控linux性能及进程消耗性能的方法
2014/07/25 Python
python爬虫常用的模块分析
2014/08/29 Python
采用Psyco实现python执行速度提高到与编译语言一样的水平
2014/10/11 Python
利用scrapy将爬到的数据保存到mysql(防止重复)
2018/03/31 Python
Python爬虫常用库的安装及其环境配置
2018/09/19 Python
Python实现微信小程序支付功能
2019/07/25 Python
联想香港官方网站及网店:Lenovo香港
2018/04/13 全球购物
linux面试题参考答案(5)
2016/11/05 面试题
4s店总经理岗位职责
2013/12/31 职场文书
运动会宣传口号
2014/06/09 职场文书
离婚财产处理协议书
2014/09/30 职场文书
部门经理迟到检讨书
2015/02/16 职场文书
2015初中教导处工作总结
2015/07/21 职场文书