这部分为Flask博客的登录页面加个验证码。使用了PIL模块生成验证码图片,并通过Flask的session机制,进行验证码验证。

1、生成验证码

使用string模块:string.ascii_letters+string.digits构造了验证码字符组合。使用的PIL模块,构建了图形对象,并进行划线和高斯模糊处理。字体文件可单独保存到工程里。绘制字符串时,draw.text的前两个参数为字符的位置,可以设置为随机数,使验证码各字符的位置不固定,并且相邻字符略有重合。get_verify_code返回了图形对象和字符串。

import random
import string
from PIL import Image, ImageFont, ImageDraw, ImageFilter def rndColor():
'''随机颜色'''
return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127)) def gene_text():
'''生成4位验证码'''
return ''.join(random.sample(string.ascii_letters+string.digits, 4)) def draw_lines(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 get_verify_code():
'''生成验证码图形'''
code = gene_text()
# 图片大小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 )
# 划线
draw_lines(draw, 2, width, height)
# 高斯模糊
im = im.filter(ImageFilter.GaussianBlur(radius=1.5))
return im, code

2、表单类

为LoginForm增加一个verify_code字段,用来输入验证码。

class LoginForm(FlaskForm):
email = StringField('Email', validators=[DataRequired(), Length(1, 64),
Email()],)
password = PasswordField('Password', validators=[DataRequired()])
verify_code = StringField('VerifyCode', validators=[DataRequired()])
remember_me = BooleanField('Keep me logged in')
submit = SubmitField('Log In')

3、视图函数 

使用io.BytesIO对象将验证码图片转化为二进制形式,直接作为响应返回前端。设置首部字段的内容格式,这样二进制的内容就能以图形形式在页面中显示。验证码字符串保存在flask.session对象中,对session的操作就像处理字典一样。程序内部使用设置中的SECRET_KEY对session数据加密后,存储在cookie中。

from io import BytesIO
@auth.route('/code')
def get_code():
image, code = get_verify_code()
# 图片以二进制形式写入
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['image'] = code
return response

在登录的视图函数中,添加验证码验证功能。注意一般验证码是不区分大小写的,这里将输入的验证码和session中保存的验证码字符串都转换成小写后再作判断。

@auth.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if session.get('image').lower() != form.verify_code.data.lower():
flash('Wrong verify code.')
return render_template('auth/login.html', form=form)
if user is not None and user.verify_password(form.password.data):
login_user(user, form.remember_me.data)
return redirect(request.args.get('next') or url_for('main.index'))
flash('Invalid username or password.')
return render_template('auth/login.html', form=form)

 

4、前端

在前端中加入了验证码图形的路径,该路径指定为生成图形响应的视图函数。当点击验证码图片时,验证码会予以更新。

{{ wtf.quick_form(form) }}
<img class="verify_code" src="/auth/code " onclick="this.src='/auth/code?'+ Math.random()">

调整下布置,最终登录表单会显示成这个样子:

下面是不同方式生成的验证码:

a. 无特效 b. 增加高斯模糊 c. 增加划线

Flask博客开发——登录验证码的更多相关文章

  1. Flask博客开发——Tinymce编辑器

    之前Flask博客的文本编辑器比较简陋,这里为博客添加个优雅易用的Tinymce文本编辑器. 1.项目中添加Tinymce 下载好Tinymce包以及语言包,并添加到项目中.添加到项目的方法,参考了这 ...

  2. Flask博客类登录注册验证模块代码(十四)

    1 文件系统 blog #博客类 App forms #表单 __init__.py user.py models #模型 __init__.py user.py static #静态文件 templ ...

  3. Flask博客开发——自定义头像

    Flask Web开发一书中,使用了与个人邮箱绑定的Gravatar图形作为用户头像.Gravatar提供的头像比较简陋,而且可能由于网络问题无法生成头像.多数社交网站和博客提供用户自定义头像功能,因 ...

  4. Node.js 从零开发 web server博客项目[登录]

    web server博客项目 Node.js 从零开发 web server博客项目[项目介绍] Node.js 从零开发 web server博客项目[接口] Node.js 从零开发 web se ...

  5. Padrino 博客开发示例

    英文版出处:http://www.padrinorb.com/guides/blog-tutorial 楼主按 拿作者自己的话说:Padrino(谐音:派骓诺)是一款基于Sinatra的优雅的Web应 ...

  6. Django个人博客开发 | 前言

    本渣渣不专注技术,只专注使用技术,不是一个资深的coder,是一个不折不扣的copier 1.前言 自学 Python,始于 Django 框架,Scrapy 框架,elasticsearch搜索引擎 ...

  7. django 简易博客开发 3 静态文件、from 应用与自定义

    首先还是贴一下源代码地址  https://github.com/goodspeedcheng/sblog 上一篇博客我们介绍了 django 如何在views中使用templates以及一些常用的数 ...

  8. django 简易博客开发 1 安装、创建、配置、admin使用

    首先贴一下项目地址吧  https://github.com/goodspeedcheng/sblog 到现在位置项目实现的功能有: 1.后台管理使用Admin ,前端显示使用bootstrap 2. ...

  9. Django博客开发实践,初学者开发经验

    python,Django初学者,开发简易博客,做了一下笔记,记录了开发的过程,功力浅薄,仅供初学者互相 交流,欢迎意见建议.具体链接:Django博客开发实践(一)--分析需求并创建项目 地址:ht ...

随机推荐

  1. Node的前端化工具

    1.页面实时更新 browser-sync start --server --files "css/*.css, *.html,js/*.js"

  2. Java 泛型进阶

    擦除 在泛型代码内部,无法获得任何有关泛型参数类型的信息. 例子1: //这个例子表明编译过程中并没有根据参数生成新的类型 public class Main2 { public static voi ...

  3. Redis主从集群的Sentinel配置

    http://www.cnblogs.com/LiZhiW/p/4851631.html

  4. ASP.NET Core 2.0 : 八.图说管道

    本文通过一张GIF动图来继续聊一下ASP.NET Core的请求处理管道,从管道的配置.构建以及请求处理流程等方面做一下详细的研究.(ASP.NET Core系列目录) 一.概述 上文说到,请求是经过 ...

  5. /etc/nginx/nginx.conf配置文件详解

    user nginx; #数值和cpu核数个数一致worker_processes 8; #worker与cpu绑定 worker_cpu_affinity 0001 0010 0100 1000 1 ...

  6. openjudge(三)

    已知三角形的三边分别是a.b.c, 先算出周长的一半s=1/2(a+b+c) 则该三角形面积S=根号[s(s-a)(s-b)(s-c)] 这个公式叫海伦--秦九昭公式 证明: 设三角形的三边a.b.c ...

  7. JavaWeb学习笔记二 Http协议和Tomcat服务器

    Http协议 HTTP,超文本传输协议(HyperText Transfer Protocol),是互联网上应用最为广泛的一种网络协议.所有的WWW文件都必须遵守这个标准.设计HTTP最初的目的是为 ...

  8. JavaScript(第十天)【Function类型】

    在ECMAScript中,Function(函数)类型实际上是对象.每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法.由于函数是对象,因此函数名实际上也是一个指向函数对象 ...

  9. Beta第五天

    听说

  10. Alpha冲刺No.5

    一.站立式会议 在助教帮助下,优先解决404的问题,将demo移植到自己项目上. 进一步制作界面. 将已做好的内容,移植到手机做部分测试,能够在同一路由子网内登录数据库. 二.实际项目进展 已经解决了 ...