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 相关文章推荐
Django自定义分页与bootstrap分页结合
Feb 22 Python
Python实现判断一行代码是否为注释的方法
May 23 Python
对python使用telnet实现弱密码登录的方法详解
Jan 26 Python
Python 实现文件打包、上传与校验的方法
Feb 13 Python
解决python Markdown模块乱码的问题
Feb 14 Python
Python 数据可视化pyecharts的使用详解
Jun 26 Python
python实现的读取网页并分词功能示例
Oct 29 Python
基于Python+Appium实现京东双十一自动领金币功能
Oct 31 Python
如何利用python之wxpy模块玩转微信
Aug 17 Python
Python开发入门——迭代的基本使用
Sep 03 Python
python实现监听键盘
Apr 26 Python
Python打包为exe详细教程
May 18 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中判断一个字符串包含另一个字符串的方法
2007/03/19 PHP
详解PHP中strlen和mb_strlen函数的区别
2014/03/07 PHP
PHP、Java des加密解密实例
2015/04/27 PHP
php文件上传你必须知道的几点
2015/10/20 PHP
PHP入门教程之数组用法汇总(创建,删除,遍历,排序等)
2016/09/11 PHP
PHP封装返回Ajax字符串和JSON数组的方法
2017/02/17 PHP
ThinkPHP+EasyUI之ComboTree中的会计科目树形菜单实现方法
2017/06/09 PHP
HTTP头隐藏PHP版本号实现过程解析
2020/12/09 PHP
javascript一个无懈可击的实例化XMLHttpRequest的方法
2010/10/13 Javascript
事件冒泡是什么如何用jquery阻止事件冒泡
2013/03/20 Javascript
Javascript数组与字典用法分析
2014/12/13 Javascript
javascript中键盘事件用法实例分析
2015/01/30 Javascript
11种ASP连接数据库的方法
2015/09/18 Javascript
JS+Canvas实现的俄罗斯方块游戏完整实例
2016/12/12 Javascript
jQuery中animate的几种用法与注意事项
2016/12/12 Javascript
JavaScript编写九九乘法表(两种任选)
2017/02/04 Javascript
浅谈jQuery的bind和unbind事件(绑定和解绑事件)
2017/03/02 Javascript
Bootstrap table学习笔记(2) 前后端分页模糊查询
2017/05/18 Javascript
Vue项目中使用jquery的简单方法
2019/05/16 jQuery
在layui中使用form表单监听ajax异步验证注册的实例
2019/09/03 Javascript
js实现简单掷骰子小游戏
2019/10/24 Javascript
JS中队列和双端队列实现及应用详解
2020/09/29 Javascript
python绘图库Matplotlib的安装
2014/07/03 Python
python批量替换多文件字符串问题详解
2018/04/22 Python
numpy数组广播的机制
2019/07/12 Python
pytorch 自定义参数不更新方式
2020/01/06 Python
详解Python 重学requests发起请求的基本方式
2020/02/07 Python
Python私有属性私有方法应用实例解析
2020/09/15 Python
用python发送微信消息
2020/12/21 Python
HTML5进阶段内联标签汇总(小篇)
2016/07/13 HTML / CSS
Sephora丝芙兰马来西亚官方网站:国际化妆品购物
2018/03/15 全球购物
英国奢侈品概念店:Base Blu
2019/05/16 全球购物
文秘专业毕业生就业推荐信
2013/11/08 职场文书
简短证婚人证婚词
2014/01/09 职场文书
竞选大队干部演讲稿
2014/09/11 职场文书
煤矿施工安全协议书
2016/03/22 职场文书