Flask博客开发——登录验证码
Posted ik-heu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask博客开发——登录验证码相关的知识,希望对你有一定的参考价值。
这部分为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博客开发——登录验证码的主要内容,如果未能解决你的问题,请参考以下文章
在Python中用Request库模拟登录:博客园(简单加密,无验证码)