随机验证码、图片验证码和邮箱发送用户验证码
随机验证码、图片验证码和邮箱发送用户验证码
一、随机验证码
随机验证码的生成比较简单一般在注册用户的时候与邮箱或者手机信息接口相结合实现发送验证码功能,随机验证码只需要使用python内置的random随机数函数,调用random模块:import random,具体实现代码块
#随机验证码
def authCode():
code = ''
for i in range(6):
current = random.randrange(0,6)#randrange随机生成0-6的数字,但不包括6
if current != i:
temp=chr(random.randint(65,90))#chr()加数字是ASCII码表中的大写A-Z字符
else:
temp=random.randint(0,9)#randint随机生成65-90的数字,包括0和9
code += str(temp) #字符串拼接
return code #返回到随机生成的6位的验证码
二、图片验证码
图片验证码的生成是关于第三方库pillow的使用,使用pillow中的PIL中的一些方法生成验证码图片。其实pillow是在PIL的基础上进行修改加工的,因为PIL由于“年久失修”仅仅支持python2.7版本,所以pillow因此诞生,在PIL上面创建的兼容版本的pillow模块,示例代码块:
#author:wylkjj
#date:2019/12/19
#-*- coding:utf-8 -*-
import random #导入随机函数模块
'''
随机验证码图片
Image内部可能会有报错问题,主要是因为没有安装python2.7,不过可以忽略掉
Image:图片
ImageDraw:画笔
ImageFont:字符处理
ImageFilter: 滤镜,边界加强(阈值更大)
'''
from PIL import Image, ImageDraw, ImageFont, ImageFilter
'''
map(遍历序列):接收两个参数,一个是函数,一个是 Iterable,
map 将传入的函数依次作用到序列的每个元素,并把结果作为新的 Iterator 返回
'''
letter_cases = "qwertyupasdfghjkxcvb" # 小写字母,去除可能干扰的i,l,o,z
upper_cases = letter_cases.upper() # 大写字母
numbers = ''.join(map(str, range(3, 10))) # 3-10数字
init_chars = ''.join((letter_cases, upper_cases, numbers))
def create_validate_code(size=(90, 30),
chars=init_chars,
img_type="GIF",
mode="RGB",
bg_color=(255, 255, 255),
fg_color=(0, 0, 255),
font_size=18,
font_type="simfang.ttf",
length=4,
draw_lines=True,
n_line=(1, 2),
draw_points=True,
point_chance = 2):
'''
@todo: 生成验证码图片
@param size: 图片的大小,格式(宽,高),默认为(90, 30)
@param chars: 允许的字符集合,格式字符串
@param img_type: 图片保存的格式,默认为GIF,可选的为GIF,JPEG,TIFF,PNG
@param mode: 图片模式,默认为RGB
@param bg_color: 背景颜色,默认为白色
@param fg_color: 前景色,验证码字符颜色,默认为蓝色#0000FF
@param font_size: 验证码字体大小
@param font_type: 验证码字体,默认为 ae_AlArabiya.ttf
@param length: 验证码字符个数
@param draw_lines: 是否划干扰线
@param n_lines: 干扰线的条数范围,格式元组,默认为(1, 2),只有draw_lines为True时有效
@param draw_points: 是否画干扰点
@param point_chance: 干扰点出现的概率,大小范围[0, 100]
@return: [0]: PIL Image实例
@return: [1]: 验证码图片中的字符串
'''
width, height = size # 宽, 高
img = Image.new(mode, size, bg_color) # 创建图形
draw = ImageDraw.Draw(img) # 创建画笔
def get_chars():
'''生成给定长度的字符串,返回列表格式(以length的数量返回chars)'''
return random.sample(chars, length)
def create_lines():
'''绘制干扰线'''
line_num = random.randint(*n_line) # 干扰线条数
for i in range(line_num):
#起始点
begin = (random.randint(0, size[0]), random.randint(0, size[1]))
#结束点
end = (random.randint(0, size[0]), random.randint(0, size[1]))
draw.line([begin, end], fill=(0, 0, 0))#fill背景色
def create_points():
'''绘制干扰点'''
chance = min(100, max(0, int(point_chance))) # 大小限制在[0, 100],省去了if else的复杂操作
for w in range(width):
for h in range(height):
tmp = random.randint(0, 100)
if tmp > 100 - chance:
draw.point((w, h), fill=(0, 0, 0))#背景色
def create_strs():
'''绘制验证码字符'''
c_chars = get_chars()
strs = ' %s ' % ' '.join(c_chars) # 每个字符前后以空格隔开
font = ImageFont.truetype(font_type, font_size)
font_width, font_height = font.getsize(strs)
draw.text(((width - font_width) / 3, (height - font_height) / 3),
strs, font=font, fill=fg_color)
return ''.join(c_chars)
if draw_lines:
create_lines()
if draw_points:
create_points()
strs = create_strs()
# 图形扭曲参数
params = [1 - float(random.randint(1, 2)) / 100,
0,0,0,
1 - float(random.randint(1, 10)) / 100,
float(random.randint(1, 2)) / 500,
0.001,
float(random.randint(1, 2)) / 500
]
img = img.transform(size, Image.PERSPECTIVE, params) # 创建扭曲
img = img.filter(ImageFilter.EDGE_ENHANCE_MORE) # 滤镜,边界加强(阈值更大)
return img, strs
#生成验证码图片(测试时可以直接调用打印数据类型判断是否生成数据)
img,strs=create_validate_code()
print(type(img),type(strs))
#生成验证码图片
import io #要导入io模块
def checkCode(req):
stream = io.BytesIO()
#创建随机字符串 code
#创建一张图片格式的字符串,将随机字符串写到图片上
img,code = create_validate_code()
img.save(stream,"PNG")
#将字符串形式的验证码放在Session中
req.session["checkCode"]=code
return HttpResponse(stream.getvalue()) #把数据返回到前端
三、邮箱发送用户验证码
邮箱发送用户验证码通常结合上面的随机验证码一起使用:把从上面获得到的数据以邮箱的方式发送到用户邮箱中。注:发送邮件的又想要打开SMTP服务,生成授权码,用授权码代替邮箱的密码进行登录操作,要使用与其邮箱相符的SMTP和端口号进行发送,下面例子使用的是网易163邮箱账号,具体的开启SMTP服务的操作请自行百度。
#邮箱发送功能
def email(email_list, content, subject="抽屉新热榜-用户注册"):
msg = MIMEText(content, 'plain', 'utf-8')
#发件人和发件邮箱
msg['From'] = formataddr(["抽屉新热榜",'######@163.com'])
#邮件主题
msg['Subject'] = subject
# SMTP服务
server = smtplib.SMTP("smtp.163.com", 25) #邮箱的smtp和端口
# SMTP登录网易邮箱账号
server.login("######@163.com", "######")
# 发送的邮箱
server.sendmail('######@163.com', email_list, msg.as_string())
server.quit()
#调用此函数就可以直接使用邮箱发送了
email(["要给发送的人的邮箱地址",], "要发送的内容")