Python生成图片验证码

最近公司网站,需要在注册模块添加验证码,防止其他人频繁的恶意注册,我们后端使用的是python进行开发,所以研究了下python图片验证码的方法。

最后确定使用python里面PIL库,通过Image, ImageDraw, ImageFont, ImageFilter的模块生成图片验证码

设计思路(这里就不画图了): (1)用户填写用户名(必须先填) (2)客户端点击获取验证码,请求里带用户名参数 (3)调用生成验证码接口 (4)按一定规则将用户名生成键值,以生成的键值为键,验证码为值,保存到缓存中 (5)将验证码的字节流返回客户端并显示 (6)输入验证码,点击注册 (7)后台根据用户名和验证码验证

生成验证码函数

1#!/usr/bin/env python 2# -*- coding: UTF-8 -*- 3 4import random 5from PIL import Image, ImageDraw, ImageFont, ImageFilter 6 7try: 8 import cStringIO as StringIO 9except ImportError: 10 import StringIO 11 12_letter_cases = "abcdefghjkmnpqrstuvwxy" # 小写字母 13_upper_cases = "ABCDEFGHJKLMNPQRSTUVWXY" # 大写字母 14_numbers = "1234567890" # 数字 15init_chars = ''.join((_letter_cases, _upper_cases, _numbers)) # 生成允许的字符集合 16default_font = "./DejaVuSans.ttf" # 验证码字体 17 18 19# 生成验证码接口 20def generate_verify_image(size=(120, 30), 21 chars=init_chars, 22 img_type="GIF", 23 mode="RGB", 24 bg_color=(255, 255, 255), 25 fg_color=(0, 0, 255), 26 font_size=18, 27 font_type=default_font, 28 length=4, 29 draw_lines=True, 30 n_line=(1, 2), 31 draw_points=True, 32 point_chance=2, 33 save_img=False): 34 35 """ 36 生成验证码图片 37 :param size: 图片的大小,格式(宽,高),默认为(120, 30) 38 :param chars: 允许的字符集合,格式字符串 39 :param img_type: 图片保存的格式,默认为GIF,可选的为GIFJPEGTIFFPNG 40 :param mode: 图片模式,默认为RGB 41 :param bg_color: 背景颜色,默认为白色 42 :param fg_color: 前景色,验证码字符颜色,默认为蓝色#0000FF 43 :param font_size: 验证码字体大小 44 :param font_type: 验证码字体,默认为 DejaVuSans.ttf 45 :param length: 验证码字符个数 46 :param draw_lines: 是否划干扰线 47 :param n_line: 干扰线的条数范围,格式元组,默认为(1, 2),只有draw_lines为True时有效 48 :param draw_points: 是否画干扰点 49 :param point_chance: 干扰点出现的概率,大小范围[0, 100] 50 :param save_img: 是否保存为图片 51 :return: [0]: 验证码字节流, [1]: 验证码图片中的字符串 52 """ 53 54 width, height = size # 宽, 高 55 img = Image.new(mode, size, bg_color) # 创建图形 56 draw = ImageDraw.Draw(img) # 创建画笔 57 58 def get_chars(): 59 """生成给定长度的字符串,返回列表格式""" 60 61 return random.sample(chars, length) 62 63 def create_lines(): 64 """绘制干扰线""" 65 66 line_num = random.randint(*n_line) # 干扰线条数 67 68 for i in range(line_num): 69 # 起始点 70 begin = (random.randint(0, size[0]), random.randint(0, size[1])) 71 # 结束点 72 end = (random.randint(0, size[0]), random.randint(0, size[1])) 73 draw.line([begin, end], fill=(0, 0, 0)) 74 75 def create_points(): 76 """绘制干扰点""" 77 78 chance = min(100, max(0, int(point_chance))) # 大小限制在[0, 100] 79 80 for w in xrange(width): 81 for h in xrange(height): 82 tmp = random.randint(0, 100) 83 if tmp > 100 - chance: 84 draw.point((w, h), fill=(0, 0, 0)) 85 86 def create_strs(): 87 """绘制验证码字符""" 88 89 c_chars = get_chars() 90 strs = ' %s ' % ' '.join(c_chars) # 每个字符前后以空格隔开 91 92 font = ImageFont.truetype(font_type, font_size) 93 font_width, font_height = font.getsize(strs) 94 95 draw.text(((width - font_width) / 3, (height - font_height) / 3), 96 strs, font=font, fill=fg_color) 97 98 return ''.join(c_chars) 99 100 if draw_lines: 101 create_lines() 102 if draw_points: 103 create_points() 104 strs = create_strs() 105 106 # 图形扭曲参数 107 params = [1 - float(random.randint(1, 2)) / 100, 108 0, 109 0, 110 0, 111 1 - float(random.randint(1, 10)) / 100, 112 float(random.randint(1, 2)) / 500, 113 0.001, 114 float(random.randint(1, 2)) / 500 115 ] 116 img = img.transform(size, Image.PERSPECTIVE, params) # 创建扭曲 117 118 img = img.filter(ImageFilter.EDGE_ENHANCE_MORE) # 滤镜,边界加强(阈值更大) 119 120 mstream = StringIO.StringIO() 121 img.save(mstream, img_type) 122 123 if save_img: 124 img.save("validate.gif", img_type) 125 126 return mstream, strs 127 128 129if __name__ == "__main__": 130 mstream, strs = generate_verify_image(save_img=True) 131 print strs

注意:返回的流要进行转换,在返回前端

self.write(simplejson.dumps({'code': 0, 'img': stream.getvalue().encode('base64')}))

这里是将stream的值进行了一次base64的编码

前端js设置图片src代码

$("#verify_code_img").attr("src", "data:image/gif;base64," + data.img);

效果

是不是很简单,下次分享前端生成图片验证码的方法

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

Python生成图片验证码 - HelloWorld