DAY6图形验证码以及短信验证码的处理
到我们点击项⽬⾸页的注册时,会弹出⼀个注册页⾯,⾥⾯需要我们后台提供图形验证码以及⼿机验证码
下⾯我们来依次处理
图形验证码的处理
我们先来简单的做个分析
⾸先当我们点击注册时,我们需要给到通过浏览器给服务器发送⼀个随机码来进⾏下次请求时双⽅的校验,⽤浏览器的Javascript⽣成UUID来解决
,通过GET请求发送(通过两个⽅⾯来考虑,第⼀个这个本⾝不需要加密,第⼆个是通过img标签⾥src默认为GET)
当我们给服务器发送了UUID之后,服务器对UUID进⾏保存,然后校验UUID,然后⽣成图⽚验证码(图⽚验证码分为三个部分,⽣成的图⽚验证码名字,图⽚⾥的验证码⽂本,
画上了验证码的图⽚),我们需要把UUID保存在redis中,且作为保存值的键,然后提取图⽚验证码的验证码⽂本作为保存的值。然后我们再给浏览器返回画上了验证码的图⽚
就可以了。这样当⽤户通过返回的图形验证码图⽚⾥的⽂字输⼊了⽂本验证码后再次给到服务器,这⾥浏览器还需要将UUID和输⼊⽂本的
⽂本验证码⼀起给到服务器。因为服务器需要通过给到的UUID作为取值的键来取上次保存的数据,也是做进⼀步的校验和实现状态保存,你是上次给我UUID的那个浏览器。只
有当两次请求给到服务器的UUID⼀致时才能够进⾏上次⽣成图⽚验证码⽂本的提取
⼤致分析完之后我们就开始写代码
浏览器前端的处理:
我们来到我们⾸页的HTML⽂件,打开我们项⽬下的index.html,然后到我们图形验证码的相关内容,
最初⽂件的img标签, src ⾥⾯有⼀堆数据,我们先复制⼀下最初的img标签,复制了然后注释掉,然后再进⾏删除
然后Ctrl加左键点击函数来到函数的内容页⾯,这⾥⾯就有我们图⽚验证码的相关内容:
最初的⽂件⾥function generateImageCode() {}⾥⾯是空的,这⾥我把代码补充了,代码我也复制再下⾯并做个简单的解释;
function generateImageCode() {
imageCodeId = generateUUID() #⽣成UUID,⽂件的最下⾯有⽣成UUID的函数,这⾥只是函数的调⽤和⽤新的变量来对imageCOdeId变量进⾏覆盖
var url = "/passport/imageCode?imageCodeId="+ imageCodeId #⾃定义⼀个URL地址的变量,后台先创建对应的视图,然后再填写对应的视图URL加上?kv 将UUID通过GET请求给到服务器后台
$(".get_pic_code").attr("src",url) #将构造好的URL给到url
}
⽂件后⾯⽣成UUID的函数
后台创造新的视图函数:
⾸先在我们的moduls⽂件夹⾥⾯再创建⼀个新的Python⽂件夹(passport)⽤来存放我们登录注册相关的相关内容,然后建⽴⼀个叫views 的Python⽂件来存放相关的视图函数
然后就是在__init__⾥⾯写⼊蓝图三步,这⾥我们需要在实例化的时候加⼊url_prefix,也就是前缀,⼀定要记得在前缀最开始加上反斜杠/
完成之后再在我们项⽬的info的__init__⽂件夹,然后导⼊注册蓝图
完成之后来到我们的视图函数页⾯进⾏视图函数的编写,这⾥先简单的编写⼀下路由和函数就可以了,后⾯我们再进⾏补全,这⾥主要是为了补全我们前端的URL地址:
当我们完成对前端⽂件的修改后,再次执⾏主⽂件并点击主页⾯的注册,然后后端查看请求就可以看到我们的UUID 了,当点击图⽚验证码时会刷新请求出现携带不同的UUID的
请求 :
这样我们图形验证码前端HTML⽂件的修改就完成了
后端代码的处理(对应视图函数的编写):
当我们去写项⽬的视图函数时需要在我们函数的⽂本注释⾥⾯写上我们的思路以及相应的实现步骤,这样⽅便我们后续代码的编写,这是⼗分重要的。
我简单的分析⼀下图⽚⾥的步骤,并对没⼀步的代码进⾏⼀个拆分
我们需要接收UUID来作为保存图⽚验证码的值以及实现第⼆次交互时的状态保持,也就是⽤户填写好验证码之后进⾏校验,这就是第⼀步:
接收参数需要在flask⾥⾯导⼊request
# 1.接受参数(imageCodeId)
imageCodeId = ("imageCodeId") (接收的get请求的数据,post为from)
对UUID进⾏简单的校验,判断是否存在这就是第⼆步:
# 2.校验参数
# 2.1校验imageCodeId是否存在
if not imageCodeId: #通过取反来判断为空,并进⾏⾃定义异常的抛出
abort(403)
抛出⾃定义异常需要flask⾥⾯导⼊abort
然后⽣成我们的图⽚验证码,这⼀步需要第三⼯具包来实现:
⾸先在我们的info⽂件夹⾥建⽴⼀个我们存放第三⽅⼯具的新⽂件夹utils,然后将我们⽣成图⽚验证码的⽂件放在⾥⾯
在⽣成图⽚验证码的captcha.py⽂件⾥⾯有测试⽤例的编写,是可以执⾏并进⾏查看是否有对应的⽣成,是可以执⾏的,记得执⾏进⾏测试确认是否能⽤。
控制台⾥⽣成的内容分别为,本次⽣成的图⽚验证码编号(也就是名字),本次⽣成的⽂字⽂档,图⽚的⼆进制格式
⽆误后在编写视图函数的views⽂件⾥⾯进⾏导⼊
注意这⾥的导⼊的三个captcha 的对应,第⼀个是captcha是⽂件夹,第⼆个是Python⽂件,第三个是⽂件⾥⾯的实例化变量
然后就可以写我们⽣成的第三步,⽣成我们的图形验证码,并进⾏拆包⽤三个变量来接收我们每⼀次⽣成的图⽚验证码的内容:
# 3.⽣成图形验证码证码
name, imageCode, image = ate_captcha() #这⾥是对元祖进⾏了拆分,每个变量存⼊不同的内容,分别是本次⽣成的图⽚验证码编号(也就是名字),
本次⽣成的⽂字⽂档(验证码⽂本),图⽚的⼆进制格式(图⽚)
完成图⽚验证码的⽣成之后就可以进⾏第四步的处理
⾸先导⼊我们创建好的连接redis数据库的变量,以及存放着我们数据设置的⽂件 constants,它⾥⾯有我们对数据的⼀些设置
然后⽤我们的数据库变量来进⾏第四步的操作
try: #因为存在连接不上数据库的问题所以需要先进⾏异常捕捉并进⾏处理
redis_store.set("imageCode"+imageCodeId,imageCode,ex=constants.IMAGE_CODE_REDIS_EXPIRES) #ex设置的是数据保存的有效时间
#键进⾏了我们接收的UUID值和前缀的拼接,值为⽣成图⽚验证码的⽂本验证码 except Exception as e :
current_(e) #这⾥需要从falsk导⼊current_app来写⼊本次异常信息并进⾏⾃定义异常的处理
abort(500)
完成之后我们完成最后⼀步返回结果,也就是给浏览器发送我们本次的⼆进制图⽚,并交给前端进⾏渲染
res=make_response(image) #这⾥我们需要对返回相应的相应头Content-Type进⾏处理,不然我们在页⾯查看源代码会是乱码,这⾥我们也需要从flask导⼊make_response res.headers["Content-Type"] = "image/jpg" return res
完成之后我们图⽚验证码的⽣成以及后续通过对⽐校验⽤户的填写是否正确就完成了,打开主页⾯的注册就会显⽰我们的图⽚验证码每次刷新也会不同:
完整的代码:
@ute("/imageCode",methods=["GET"])
def image_code():
"""
提供图⽚验证码
1.接受参数 (imageCodeId)
2.校验参数
2.1 校验imageCodeId是否存在
3.⽣成图形验证码
4.将⽂字的图形验证码保存到redis
5.返回结果
:return:
"""
# 1.接受参数(imageCodeId)
imageCodeId = ("imageCodeId")
# 2.校验参数
# 2.1校验imageCodeId是否存在
if not imageCodeId:
abort(403)
# 3.⽣成图形验证码证码把存到redis
name, imageCode, image = ate_captcha()
print(imageCode)
# 4.将⽂字的图形验证码保存到rides
try:
redis_store.set("imageCode"+imageCodeId,imageCode,ex=constants.IMAGE_CODE_REDIS_EXPIRES)
except Exception as e :
current_(e)
abort(500)
# 5.返回结果
res=make_response(image)url编码处理
res.headers["Content-Type"] = "image/jpg"
return res
短信验证码的处理
短信验证码的处理需要通过下图中的接⼝设计来实现,因为我们需要通过第三⽅给⽤户,所以有⼀个规范。
前端代码的处理
⾸先我们还是先来处理前端的HTML,⾸先到短信验证码的相关代码
然后Ctrl加⿏标左键点击进⼊函数的⽂件后到⼿机验证码对应的函数,然后进⾏修改,下⾯是⼿机验证码的函数代码
// 验证码
function sendSMSCode() {
// 校验参数,保证输⼊框有数据填写
$(".get_code").removeAttr("onclick");
var mobile = $("#register_mobile").val();
if (!mobile) {
$("#register-mobile-err").html("请填写正确的⼿机号!");
$("#register-mobile-err").show();
$(".get_code").attr("onclick", "sendSMSCode();");
return;
}
var imageCode = $("#imagecode").val();
if (!imageCode) {
$("#image-code-err").html("请填写验证码!");
$("#image-code-err").show();
$(".get_code").attr("onclick", "sendSMSCode();");
return;
}
var params = {
'mobile':mobile, #⽤户填写的⼿机号,需要给到服务器
'image_code':imageCode, # ⽤户填写的短信验证码,需要给到服务器
'image_code_id':imageCodeId #⽤户本次⽣成图形验证码的UUID
};
// TODO 验证码
$.ajax({ #规范的接⼝设计,包括请求地址以及⽅式和参数
url:'/passport/sms_code', // 请求地址
type:'post', // 请求⽅法
data:JSON.stringify(params),// 请求参数
contentType:'application/json',// 数据类型
success:function (response) { // 回调函数
if ( == '0') {
/
/ 验证码成功
sg);
} else {
sg);
}
}
});
}
前端页⾯代码的修改完成之后,编写后端的代码。
后端代码的处理(对应视图函数的编写):
和图⽚验证码⼀样,我们需要在passport⽂件夹的views⽂件⾥写⼊对应的视图函数,也就是写在我们图⽚验证码的后⾯。
⾸先写⼊对应的视图函数名和URL地址,这⾥我们规定了只接收post请求,这是按照⼀开始的接⼝规范来设置的。
完成之后我们也需要先写⼊注释⽂档,说明函数的作⽤以及分析思路并写⼊实现的步骤顺序。
⾸先该函数的作⽤为:注册时短信验证码的发送
然后先做个简单的分析
第⼀步肯定还是接收参数,这次我们根据接⼝设计的图⽚得知我们有三个参数需要接收
1,⽤户填写的⼿机号
2,⽤户填写的短信验证码
3,浏览器⽣成的UUID (这个是⽤来校验图形验证码)
第⼆步校验参数,⾸先检查是否传全,然后分别检验
第三步当数据全且⽆误时,在后台⽣成我们的4位数的短信验证码
第四步将验证码保存到我们的数据库中
第五步通过第三⽅给⽤户发送我们后天⽣成的验证码
第六步返回结果
""" #函数的注释⽂档
注册时短信发送
1. 接收参数(mobile,image_code,image_code_id)
2. 校验参数
2.1 判断参数是否齐全(mobile,image_code,image_code_id)
2.2 校验⼿机号是否正确,正则
2.3 查看redis 是否有image_code_id
否:返回json数据
2.4 校验⽤户填写的验证码是否正确
否:返回json数据
3.⽣成短信验证码
4.将短信验证码保存到redis
5.发送⼿机短信
否:返回json数据
6.返回结果
:return:
"""
下⾯我们还是通过编写每⼀步的代码来实现整个短信验证码的功能
第⼀步
# 1. 接收参数(mobile,image_code,image_code_id)
mobile=("mobile") #接收json数据对应的参数
image_code=("image_code")
image_code_id=("image_code_id")
所有接收的变量的命名是通过最开始的端⼝设计规范来写的,以及规定了发送的是json数据,所以我们对json 数据进⾏接收.request.json,这⾥还是⽤了flask的request包第⼆步
# 2. 校验参数
# 2.1 判断参数是否齐全(mobile,image_code,image_code_id)
if not all([mobile,image_code,image_code_id]):
return jsonify(errno=RET.PARAMERR,errmsg="参数缺失")
# 2.2 校验⼿机号是否正确,正则
mobile=mobile.strip() #去空
if not re.findall("^1[3|4|5|7|8][0-9]{9}$",mobile):
return jsonify(errno=RET.PARAMERR,errmsg="⼿机号格式有误")
# 2.3 查看redis 是否有image_code_id
try: #对数据库连接进⾏异常捕捉
image_code_server = ("imageCode" + image_code_id)
except Exception as e :
current_(e)
return jsonify(errno=RET.DBERR,errmsg="数据库连接失败")
# 否:返回json数据
if not image_code_server: #没有到对应键值对json数据的返回
return jsonify(errno=RET.NODATA,errmsg="未到该图⽚验证码")
# 2.4 校验⽤户填写的验证码是否正确
if image_code_server.strip().lower() != image_code.strip().lower(): #去空strip,⼩写lower
return jsonify(errno=RET.PARAMERR,errmsg="图⽚验证码填写错误")
# 否:返回json数据
⾸先判断所有参数是否齐全,通过if not 取反即可,然后是通过⼿机号的正则写法来判断⼿机号是否正确,这⾥返回json数据也是通过最开始的接⼝设计,
通过flask导⼊jsonify就可以给前端返回json数据
通过规范我们得知需要返回两个参数,分别是 errno(错误码),errmsg(错误信息),错误信息有我们⾃⼰填写字符串来进⾏本次错误的描述,⽽错误码在我们之前复制到项⽬的response_code.py的⽂件中
它⾥⾯有⼀个记录了errno的类RET,以及每个类属性的中⽂注释
我们将它导⼊到我们的视图⽂件views中,然后通过调⽤类属性的⽅法也就是对象.的形式来进⾏相关的调⽤
当我们进⾏第三⽅操作时,就需要进⾏异常捕捉,数据库有时候会连接不上
当我们查看redis 是否有image_code_id,也就是redis保存的⽂字验证码是否存在,这⾥需要先查看所UUID的值拼接上
前缀所产⽣的键是否存在,当和最开始拼接的保存⽂字验证码的键⼀致时,就可以取出⾥⾯的⽂字验证码来对⽤户输⼊的
⽂字验证码进⾏校验,所以⾸先我们先判断键值对是否存在,然后再通过取出值来判断⽤户输⼊的⽂字验证码是否正确,也就是
image_code.这⾥我们为了⽤户体验进⾏了字符串去空和⼩写的设置,这⼀步也是很重要的,⼿机号也进⾏了去空。这样我们接收的三个数据
也就分别校验完毕了
第三步
3.⽣成短信验证码
smsCode="%04d" %random.randint(0, 9999)
这⼀步通过了导⼊random随机数包来⽣成最⼤位数为4位的随机数,然后通过格式化输出中不满⾜位数⾃动补0的⽅法来进⾏完成验证码的⽣成。
第四步
# 4.将短信验证码保存到redis #对数据库连接异常进⾏捕捉
try:
redis_store.set("SMScode:"+mobile,smsCode,ex=constants.SMS_CODE_REDIS_EXPIRES) #ex 设置有效时长
except Exception as e :
current_(e)
return jsonify(errno=RET.DBERR,errmsg="数据库连接失败")
当我们使⽤第三⽅⼯具时都需要进⾏异常捕捉,因为我们不确定我们与第三⽅之间的连接是否正常,问题随时都有可能发⽣,所以进⾏异常捕捉的处理
这⾥我们也对键进⾏了拼接,前缀+⽤户的⼿机号,然后设置了保存的有效时长,⽅法同保存的图⽚验证验证码时长⼀样,然后对错误json数据的返回
第五步
# 5.发送⼿机短信
# try:
# sms_res = CCP().send_template_sms(mobile, [smsCode, constants.SMS_CODE_REDIS_EXPIRES / 60], 1) #复制测试时⽂件的代码,进⾏相关的修改
# except Exception as e :
# current_(e)
# return jsonify(errno=RET.THIRDERR,errmsg="失败")
sms_res = 0
if sms_res != 0 :
return jsonify(errno=RET.THIRDERR,errmsg="失败")
# 否:返回json数据
if sms_res != 0 : #通过查看元⽂件代码可以发现发送成功会返回结果0,
失败为-1,所以还需要对结果进⾏校验,这⾥的问题有可能是第三⽅不能给⽤户所造成的
return jsonify(errno=RET.THIRDERR,errmsg="失败")
这⾥需要导⼊我们第⼆个第三⽅⼯具包
⾸先在info⾥⾯再创建⼀个新的⽂件夹libs来存放第三⽅平台
libs⽤来存放第三⽅平台,然后utils⽤来存放第三⽅⽂件
将我们的第三⽅平台的⽂件夹复制到⾥⾯,还是先进⼊到我们要使⽤的sms.py⾥⾯执⾏进⾏测试
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论