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/ironpython:从入门到精通
Oct 02 Python
Python的gevent框架的入门教程
Apr 29 Python
从源码解析Python的Flask框架中request对象的用法
Jun 02 Python
Python2包含中文报错的解决方法
Jul 09 Python
python 实现求解字符串集的最长公共前缀方法
Jul 20 Python
Python正则表达式指南 推荐
Oct 09 Python
Pycharm无法使用已经安装Selenium的解决方法
Oct 13 Python
在Pycharm中执行scrapy命令的方法
Jan 16 Python
解决pycharm回车之后不能换行或不能缩进的问题
Jan 16 Python
在脚本中单独使用django的ORM模型详解
Apr 01 Python
使用Python内置模块与函数进行不同进制的数的转换
Apr 26 Python
解决numpy和torch数据类型转化的问题
May 23 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
DOTA2 1月28日更新:监管系统降临刀塔世界
2021/01/28 DOTA
php strlen mb_strlen计算中英文混排字符串长度
2009/07/10 PHP
php根据身份证号码计算年龄的实例代码
2014/01/18 PHP
php使用ffmpeg获取视频信息并截图的实现方法
2016/05/03 PHP
php json_encode与json_decode详解及实例
2016/12/13 PHP
PHP中的使用curl发送请求(GET请求和POST请求)
2017/02/08 PHP
PHP 代码简洁之道(小结)
2019/10/16 PHP
JavaScript中令你抓狂的魔术变量
2006/11/30 Javascript
jquery图片放大镜功能的实例代码
2013/03/26 Javascript
在Firefox下js select标签点击无法弹出
2014/03/06 Javascript
AngularJS基础学习笔记之控制器
2015/05/10 Javascript
JavaScript中isPrototypeOf函数作用和使用实例
2015/06/01 Javascript
js右下角弹出提示框示例代码
2016/01/12 Javascript
Vue数据驱动模拟实现2
2017/01/11 Javascript
详解利用 Vue.js 实现前后端分离的RBAC角色权限管理
2017/09/15 Javascript
深入理解Node.js中通用基础设计模式
2017/09/19 Javascript
vue2.0 常用的 UI 库实例讲解
2017/12/12 Javascript
JS实现DOM删除节点操作示例
2018/04/04 Javascript
Angular6 正则表达式允许输入部分中文字符
2018/09/10 Javascript
Vue自动构建发布脚本的方法示例
2020/07/24 Javascript
vue-cli3中配置alias和打包加hash值操作
2020/09/04 Javascript
基于python requests库中的代理实例讲解
2018/05/07 Python
python使用xlrd模块读取xlsx文件中的ip方法
2019/01/11 Python
python使用wxpy轻松实现微信防撤回的方法
2019/02/21 Python
利用python生成照片墙的示例代码
2020/04/09 Python
css3实现顶部社会化分享按钮示例
2014/05/06 HTML / CSS
一个不错的HTML5 Canvas多层点击事件监听实例
2014/04/29 HTML / CSS
英国Office鞋店德国网站:在线购买鞋子、靴子和运动鞋
2018/12/19 全球购物
Paradox London官方网站:英国新娘鞋婚礼鞋品牌
2019/08/29 全球购物
买卖正宗运动鞋:GOAT
2019/12/06 全球购物
美国农场商店:Blain’s Farm & Fleet
2020/01/17 全球购物
工作表扬信的范文
2014/01/10 职场文书
顶撞领导检讨书
2014/01/29 职场文书
党的群众路线教育实践活动公开承诺书
2014/03/28 职场文书
《赠汪伦》教学反思
2014/04/12 职场文书
护理工作个人总结
2015/03/03 职场文书