flask实现验证码并验证功能


Posted in Python onDecember 05, 2019

什么是Flask?

Flask是一个用Python编写的Web应用程序框架,Flask是python的web框架,最大的特征是轻便,让开发者自由灵活的兼容要开发的feature。 它由 Armin Ronacher 开发,他领导一个名为Pocco的国际Python爱好者团队。 Flask基于Werkzeug WSGI工具包和Jinja2模板引擎。两者都是Pocco项目。

效果图:

点击图片、刷新页面、输入错误点击登录时都刷新验证码

flask实现验证码并验证功能

实现步骤:

第一步:先定义获取验证码的接口

verificationCode.py

#验证码
@api.route('/imgCode')
def imgCode():
  return imageCode().getImgCode()

此处的@api是在app下注册的蓝图,专门用来做后台接口,所以注册了api蓝图

flask实现验证码并验证功能

第二步:实现接口逻辑

1)首先实现验证码肯定要随机生成,所以我们需要用到random库,本次需要随机生成字母和数字,

所以我们还需要用到string。string的ascii_letters是生成所有字母 digits是生成所有数字0-9。具体代码如下

def geneText():
  '''生成4位验证码'''
  return ''.join(random.sample(string.ascii_letters + string.digits, 4)) #ascii_letters是生成所有字母 digits是生成所有数字0-9

2)为了美观,我们需要给每个随机字符设置不同的颜色。我们这里用一个随机数来给字符设置颜色

def rndColor():
  '''随机颜色'''
  return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))

3)此时我们已经可以生产图片验证码了,利用上面的随机数字和随机颜色生成一个验证码图片。

这里我们需要用到PIL库,此时注意,python3安装这个库的时候不是pip install PIL 而是pip install pillow。

def getVerifyCode():
  '''生成验证码图形'''
  code = geneText()
  # 图片大小120×50
  width, height = 120, 50
  # 新图片对象
  im = Image.new('RGB', (width, height), 'white')
  # 字体
  font = ImageFont.truetype('app/static/arial.ttf', 40)
  # draw对象
  draw = ImageDraw.Draw(im)
  # 绘制字符串
  for item in range(4):
    draw.text((5 + random.randint(-3, 3) + 23 * item, 5 + random.randint(-3, 3)),
         text=code[item], fill=rndColor(), font=font)
  return im, code

4)此时,验证码图片已经生成。然后需要做的就是把图片发送到前端去展示。

def getImgCode():
  image, code = getVerifyCode()
  # 图片以二进制形式写入
  buf = BytesIO()
  image.save(buf, 'jpeg')
  buf_str = buf.getvalue()
  # 把buf_str作为response返回前端,并设置首部字段
  response = make_response(buf_str)
  response.headers['Content-Type'] = 'image/gif'
  # 将验证码字符串储存在session中
  session['imageCode'] = code
  return response

这里我们采用讲图片转换成二进制的形式,讲图片传送到前端,并且在这个返回值的头部,需要标明这是一个图片。

将验证码字符串储存在session中,是为了一会在登录的时候,进行验证码验证。

5)OK,此时我们的接口逻辑已经基本完成。然后我们还可以给图片增加以下干扰元素,比如增加一点横线。

def drawLines(draw, num, width, height):
  '''划线'''
  for num in range(num):
    x1 = random.randint(0, width / 2)
    y1 = random.randint(0, height / 2)
    x2 = random.randint(0, width)
    y2 = random.randint(height / 2, height)
    draw.line(((x1, y1), (x2, y2)), fill='black', width=1)

然后getVerifyCode函数需要新增一步

def getVerifyCode():
  '''生成验证码图形'''
  code = geneText()
  # 图片大小120×50
  width, height = 120, 50
  # 新图片对象
  im = Image.new('RGB', (width, height), 'white')
  # 字体
  font = ImageFont.truetype('app/static/arial.ttf', 40)
  # draw对象
  draw = ImageDraw.Draw(im)
  # 绘制字符串
  for item in range(4):
    draw.text((5 + random.randint(-3, 3) + 23 * item, 5 + random.randint(-3, 3)),
         text=code[item], fill=rndColor(), font=font)
  # 划线
  drawLines(draw, 2, width, height)
  return im, code

最终接口逻辑完成。整体接口代码如下

from .. import *
from io import BytesIO
import random
import string
from PIL import Image, ImageFont, ImageDraw, ImageFilter
#验证码
@api.route('/imgCode')
def imgCode():
  return imageCode().getImgCode()
class imageCode():
  '''
  验证码处理
  '''
  def rndColor(self):
    '''随机颜色'''
    return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))
  def geneText(self):
    '''生成4位验证码'''
    return ''.join(random.sample(string.ascii_letters + string.digits, 4)) #ascii_letters是生成所有字母 digits是生成所有数字0-9
  def drawLines(self, draw, num, width, height):
    '''划线'''
    for num in range(num):
      x1 = random.randint(0, width / 2)
      y1 = random.randint(0, height / 2)
      x2 = random.randint(0, width)
      y2 = random.randint(height / 2, height)
      draw.line(((x1, y1), (x2, y2)), fill='black', width=1)
  def getVerifyCode(self):
    '''生成验证码图形'''
    code = self.geneText()
    # 图片大小120×50
    width, height = 120, 50
    # 新图片对象
    im = Image.new('RGB', (width, height), 'white')
    # 字体
    font = ImageFont.truetype('app/static/arial.ttf', 40)
    # draw对象
    draw = ImageDraw.Draw(im)
    # 绘制字符串
    for item in range(4):
      draw.text((5 + random.randint(-3, 3) + 23 * item, 5 + random.randint(-3, 3)),
           text=code[item], fill=self.rndColor(), font=font)
    # 划线
    self.drawLines(draw, 2, width, height)
    return im, code
  def getImgCode(self):
    image, code = self.getVerifyCode()
    # 图片以二进制形式写入
    buf = BytesIO()
    image.save(buf, 'jpeg')
    buf_str = buf.getvalue()
    # 把buf_str作为response返回前端,并设置首部字段
    response = make_response(buf_str)
    response.headers['Content-Type'] = 'image/gif'
    # 将验证码字符串储存在session中
    session['imageCode'] = code
    return response

第三步:前端展示。

这里前端我使用的是layui框架。其他框架类似。

<div class="layui-form-item">
  <label class="layui-icon layui-icon-vercode" for="captcha"></label>
  <input type="text" name="captcha" lay-verify="required|captcha" placeholder="图形验证码" autocomplete="off"
      class="layui-input verification captcha" value="">
  <div class="captcha-img">
    <img id="verify_code" class="verify_code" src="/api/imgCode" onclick="this.src='/api/imgCode?'+ Math.random()">
  </div>
</div>

js:主要是针对验证失败以后,刷新图片验证码

// 进行登录操作
      form.on('submit(login)', function (data) {
        console.log(data.elem);
        var form_data = data.field;
        //加密成md5
        form_data.password=$.md5(form_data.password);
        $.ajax({
          url: "{{ url_for('api.api_login') }}",
          data: form_data,
          dataType: 'json',
          type: 'post',
          success: function (data) {
            if (data['code'] == 0) {
              location.href = "{{ url_for('home.homes') }}";
            } else {
              //登录失败则刷新图片验证码
              var tagImg = document.getElementById('verify_code');
              tagImg.src='/api/imgCode?'+ Math.random();
              console.log(data['msg']);
              layer.msg(data['msg']);
            }
          }
        });
        return false;
      });

第四步:验证码验证

验证码验证需要在点击登录按钮以后,在对验证码进行效验

1)首先我们获取到前端传过来的验证码。.lower()是为了忽略大小写

这里的具体写法为什么这样写可以获取到前端传过来的参数,可以自行了解flask框架

if request.method == 'POST':
  username = request.form.get('username')
  password = request.form.get('password')
  captcha = request.form.get('captcha').lower()

2)对验证码进行验证.因为我们在生成验证码的时候,就已经把验证码保存到session中,这里直接取当时生成的验证码,然后跟前端传过来的值对比即可。

if captcha==session['imageCode'].lower():
   pass
 else:
   return jsonify({'code':-1,'msg':'图片验证码错误'})

到此,已完成了获取验证码、显示验证码、验证验证码的所有流程。验证验证码中没有把整体代码写出来。可以根据自己情况自己写。

总结

以上所述是小编给大家介绍的flask实现验证码并验证功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Python 相关文章推荐
给Python初学者的一些编程技巧
Apr 03 Python
Python3.x中自定义比较函数
Apr 24 Python
Python中设置变量访问权限的方法
Apr 27 Python
Python xlrd读取excel日期类型的2种方法
Apr 28 Python
python实现类的静态变量用法实例
May 08 Python
python机器学习之决策树分类详解
Dec 20 Python
Python统计纯文本文件中英文单词出现个数的方法总结【测试可用】
Jul 25 Python
在python中使用xlrd获取合并单元格的方法
Dec 26 Python
django框架模板中定义变量(set variable in django template)的方法分析
Jun 24 Python
利用rest framework搭建Django API过程解析
Aug 31 Python
Windows平台Python编程必会模块之pywin32介绍
Oct 01 Python
解决windows下python3使用multiprocessing.Pool出现的问题
Apr 08 Python
使用python写一个自动浏览文章的脚本实例
Dec 05 #Python
Python字节单位转换实例
Dec 05 #Python
使用Python paramiko模块利用多线程实现ssh并发执行操作
Dec 05 #Python
Python使用指定字符长度切分数据示例
Dec 05 #Python
python从zip中删除指定后缀文件(推荐)
Dec 05 #Python
python3 求约数的实例
Dec 05 #Python
python生成特定分布数的实例
Dec 05 #Python
You might like
NO3第三帝国留言簿制作过程
2006/10/09 PHP
PHP 文件编程综合案例-文件上传的实现
2013/07/03 PHP
php 如何获取数组第一个值
2013/08/06 PHP
php获取本机真实IP地址实例代码
2016/03/31 PHP
JavaScript 原型学习总结
2010/10/29 Javascript
基于jQuery的获取标签名的代码
2012/07/16 Javascript
js获取class的所有元素
2013/03/28 Javascript
JQuery DataTable删除行后的页面更新利用Ajax解决
2013/05/17 Javascript
仿百度输入框智能提示的js代码
2013/08/22 Javascript
jquery获取radio值(单选组radio)
2014/10/16 Javascript
js实现发送验证码后的倒计时功能
2015/05/28 Javascript
WordPress中利用AJAX技术进行评论提交的实现示例
2016/01/12 Javascript
JavaScript中创建对象的7种模式详解
2017/02/21 Javascript
Vue.js实战之利用vue-router实现跳转页面
2017/04/01 Javascript
JS禁止浏览器右键查看元素或按F12审查元素自动关闭页面示例代码
2017/09/07 Javascript
移动端效果之Swiper详解
2017/10/09 Javascript
jQuery中ajax获取数据赋值给页面的实例
2017/12/31 jQuery
DJANGO-ALLAUTH社交用户系统的安装配置
2014/11/18 Python
Python学习小技巧之利用字典的默认行为
2017/05/20 Python
Django中使用第三方登录的示例代码
2018/08/20 Python
情人节快乐! python绘制漂亮玫瑰
2020/08/18 Python
python2 中 unicode 和 str 之间的转换及与python3 str 的区别
2019/07/25 Python
python中使用.py配置文件的方法详解
2020/11/23 Python
.NET初级开发工程师面试题(包括Javascript)
2012/08/22 面试题
Python如何实现单例模式
2016/06/03 面试题
工程总经理工作职责
2013/12/09 职场文书
党员的自我评价范文
2014/01/02 职场文书
电子信息专业自荐书
2014/02/04 职场文书
高校教师岗位职责
2014/03/18 职场文书
劲霸男装广告词
2014/03/21 职场文书
爱护公共设施标语
2014/06/24 职场文书
社区党建工作汇报材料
2014/08/14 职场文书
2015年收银员个人工作总结
2015/04/01 职场文书
2015年学生会主席工作总结
2015/04/21 职场文书
公司与个人合作协议书
2016/03/19 职场文书
opencv深入浅出了解机器学习和深度学习
2022/03/17 Python