更新备案 网站 打开,零基础怎么做电商,网站搜索栏建立,网站的登录弹窗怎么做1 图形验证码接口设计 将后端⽣成的图⽚验证码存储在redis数据库2号库。
结构#xff1a;
{img_uuid:0594}
1.1 创建验证码⼦应⽤
$ cd apps
$ python ../../manage.py startapp verifications
# 注册新应⽤
INSTALLED_APPS [django.contrib.admin,django.contrib.auth,…1 图形验证码接口设计 将后端⽣成的图⽚验证码存储在redis数据库2号库。
结构
{img_uuid:0594}
1.1 创建验证码⼦应⽤
$ cd apps
$ python ../../manage.py startapp verifications
# 注册新应⽤
INSTALLED_APPS [django.contrib.admin,django.contrib.auth,django.contrib.contenttypes,django.contrib.sessions,django.contrib.messages,django.contrib.staticfiles,userapp,newsapp,verifications,
]
1.2 图形验证码接⼝设计
1.2.1 请求⽅式
选项⽅案请求⽅法GET请求地址 1/imgcodes/(?P[\w-])/
1.2.2 请求参数路径参数
参数名类型是否必传说明uuidstring是唯⼀编号
1.2.3 响应结果 图⽚验证码格式image/png 1.3 图形验证码接⼝定义
1.3.1 图形验证码视图
# views.py视图⽂件
class ImageCode(View):def get(self, request, uuid):pass
1.3.2 配置路由
# 项⽬根路由
re_path(^, include((verifications.urls, verifications,),namespaceverify)),
# ⼦路由
re_path(^image_code/(?Puuid[\w-])/$, views.ImageCode.as_view())
2 图片验证码后端逻辑
2.1 配置Redis数据库
# 配置redis数据库专⻔存储验证码
verify_code: { # 验证码BACKEND: django_redis.cache.RedisCache,LOCATION: redis://192.168.1.6:6379/2,OPTIONS: {CLIENT_CLASS: django_redis.client.DefaultClient,}
}
2.2 安装模块
pip install pillow
pip install captcha
2.3 图⽚验证码视图
# constants.py⽂件内容
# 图⽚验证码有效期单位秒
IMAGE_CODE_REDIS_EXPIRES 300# views.py视图⽂件
from captcha.image import ImageCaptcha
from django_redis import get_redis_connection
from newsdemo.apps.verifications import constantsclass ImageCode(View):def get(self, request, uuid):# 随机⽣成四位数字seeds string.digitsrandom_str random.choices(seeds, k4)imgcode .join(random_str)# ⽣成图⽚验证码img ImageCaptcha().generate(charsimgcode)# 保存图⽚验证码到redisredis_conn get_redis_connection(verify_code)redis_conn.setex(img_%s % uuid, constants.IMAGE_CODE_REDIS_EXPIRES, imgcode)return http.HttpResponse(img, content_typeimage/png)3 图片验证码前端逻辑
3.1 Vue实现图形验证码展示
3.1.1 register.js
mounted(){// ⽣成图形验证码this.generate_img_code();},
methods:{generate_img_code:function () {// ⽣成UUID generateUUID() : 封装在common.js⽂件中需要提前引⼊this.uuid generateUUID();// 拼接图形验证码请求地址this.img_url /imgcodes/ this.uuid /;},
...
}
3.1.2 register.html
p classform-row form-row-wideinput stylewidth: 250px; placeholder图⽚验证码typetext classinput-textimg styleheight: 40px;float: right; :srcimg_urlclickgenerate_img_codespan classerror-tip图⽚验证码有误/span
/p3.1.3 图形验证码展示和存储效果 3.2 Vue实现图形验证码校验
3.2.1 register.html
p classform-row form-row-wideinput stylewidth: 250px; placeholder图⽚验证码 v-modelimgcode blurcheck_imgcode nameimgcodetypetext classinput-textimg styleheight: 40px;float: right; :srcimg_urlclickgenerate_img_codespan classerror-tip v-showerror_imgcode${error_imgcode_msg}/span
/p
3.2.2 register.js
// 校验图⽚验证码
check_imgcode:function () {if (!this.imgcode) {this.error_imgcode_msg 请填写图⽚验证码;this.error_imgcode true;} else {this.error_imgcode false;}
}
3.2.3 校验效果 4 短信验证码接口设计 4.1 短信验证码接⼝设计
4.1.1 请求⽅式
选项⽅案请求⽅法GET请求地址 1/sms_codes/(?P1[35789]\d{9})/
4.1.2 请求参数路径参数和查询字符串
参数名类型是否必传说明phonestring是⼿机号imgcodestring是图⽚验证码uuidstring是唯⼀编号
4.1.3 响应结果JSON
响应结果响应内容code状态码errmsg错误信息
4.2 短信验证码接⼝定义
class SMSCode(View):短信验证码def get(self, reqeust, phone)::param reqeust: 请求对象:param phone: ⼿机号:return: JSONpass
4.3 知识要点
保存短信验证码是为注册做准备的。为了避免⽤户使⽤图形验证码恶意测试后端提取了图形验证码后⽴即删除图形验证码。Django不具备发送短信的功能所以我们借助 第三⽅的互亿⽆线短信平台 来帮助我们发送短信验证码。
5 互亿无线短信平台
5.1 平台介绍
互亿⽆线官⽹ https://www.ihuyi.com/
⽬前注册可免费使⽤50条短信验证码
5.2 平台管理中⼼ 5.3 接⼊⽂档
跳转地址短信验证码接入指南_短信平台帮助_互亿无线 (ihuyi.com)
5.4 配置参数
在dev.py配置⽂件中添加参数
# 互亿⽆线短信验证码参数
# APIID
APIID C74**64
# APIKEY
APIKEY 62de***8932d50c2
5.5 下载Python3.8⽀持的SDK
# utils/huyi_sms/sms3.py
# !/usr/local/bin/python
# -*- coding:utf-8 -*-
from urllib.request import urlopen
from urllib.parse import urlencode
from django.conf import settings
import jsondef send_sms_code(smscode, phone):# APIID(⽤户中⼼【验证码通知短信】-【产品纵览】查看)account settings.APIID# APIKEY(⽤户中⼼【验证码通知短信】-【产品纵览】查看)password settings.APIKEYtext 您的验证码是%s。请不要把验证码泄露给其他⼈。 % smscodedata {account: account, password: password, content: text,mobile: phone, format: json}req urlopen(urlhttps://106.ihuyi.com/webservice/sms.php?methodSubmit,dataurlencode(data).encode())content req.read().decode()print(content)# code等于2代表提交成功否则提交失败# smsid等于0代表提交失败否则显示⻓度20流⽔号# b{code:2,msg:\xe6\x8f\x90\xe4\xba\xa4\xe6\x88\x90\xe5\x8a\x9f,# smsid:16063783563405105174}return json.loads(content) 6 短信验证码后端逻辑
6.1 短信验证码后端逻辑实现
class SMScodeView(View):def get(self, request, phone):匹配并删除图形验证码发送短信验证码:param request::param phone::return:# 1. 获取请求参数路径参数查询参数imgcode_client request.GET.get(imgcode, )uuid request.GET.get(uuid, )# 2. 校验参数if not all([phone, imgcode_client, uuid]):return JsonResponse({code: 4001, errormsg: 缺少必须传递的参数})# 3. 校验图⽚验证码⽤户输⼊验证码和⽣成验证码redis_conn django_redis.get_redis_connection(verify_code)imgcode_server redis_conn.get(img_%s % uuid)print(uuid)print(imgcode_server)# 3.1 图⽚验证码是否过期if imgcode_server is None:return JsonResponse({code: 4002, errormsg: 图⽚验证码已经过期})# 3.2 匹配图⽚验证码if imgcode_client.lower() ! imgcode_server.decode(utf-8).lower():return JsonResponse({code: 4003, errormsg: 图⽚验证码不匹配})try:# 删除redis中的图⽚验证码redis_conn.delete(img_%s % uuid)except Exception as e:logger.error(e)# 4. ⽣成短信验证码6位seed string.digitsr random.choices(seed, k6)smscode_str .join(r)# 5. 保存短信验证码redis数据库2号库存储redis_conn.setex(sms_%s % uuid, 60, smscode_str)# 6. 发送短信验证码ret send_sms_code(smscode_str, phone)if ret.code 2:return JsonResponse({code: 200, errormsg: OK})# 7. 返回响应结果return JsonResponse({code: 5001, errormsg: 发送短信验证码错误})
7 短信验证码前端逻辑
7.1 Vue绑定短信验证码
7.1.1 register.html
p classform-row form-row-wideinput stylewidth: 250px; placeholder短信验证码 v-modelsmscodeblurcheck_smscode namemsgcodetypetext classinput-text idreg_mescodespan classerror-tip v-showerror_code${error_msgcode_msg}/spana hrefjavascript:; styleposition: relative;left:150px;clicksend_code()${smscode_btn} /a
/p
7.1.2 register.js
check_smscode:function () {//获取验证码⻓度let reg /^\d{6}$/;//校验规则if (!reg.test(this.smscode)) {this.error_smscode_msg 请填写短信验证码;this.error_smscode true;} else {this.error_smscode false;}
}
7.2 axios请求短信验证码
7.2.1 发送短信验证码事件处理
send_smscode:function () {//发送短信验证码//1.判断短信验证码是否正在发送if (this.send_flag) {return;}//2.修改发送状态this.send_flag true;//3.校验⽤户输⼊的⼿机号和图⽚验证码this.check_phone();this.check_imgcode();if (this.error_phone || this.error_imgcode) {this.send_flag false;return;}//4.发送短信验证码var url /smscodes/ this.phone /?imgcode this.imgcode uuid this.uuid;axios.get(url, {responseType: json}).then(response {console.log(response.data.code);console.log(typeof (response.data.code));if (response.data.code 200) {let num 60;var i setInterval(() {if (num 1) {clearInterval(i);this.smscode_btn 获取短信验证码;this.send_flag false;} else {num - 1;this.smscode_btn 倒计时 num 秒;}}, 1000, 60)} else {if (response.data.data 4001 || response.data.data 4002|| response.data.data 4003 || response.data.data 5001) {this.error_smscode_msg response.data.errormsg;this.error_smscode true;}//重新⽣成图⽚验证码this.generate_imgcode();//重置发送状态this.send_flag false;}}).catch(error {console.log(error.response);});
}
8 用户注册时短信验证码校验功能
8.1 注册时短信验证前端逻辑
8.1.1 register.html
p classform-row form-row-wideinput stylewidth: 230px; v-modelsmscode placeholder短信验证码blurcheck_smscode namemsgcodetypetext classinput-text idreg_mescodespan classerror-tip v-showerror_smscode${error_smscode_msg}/spana hrefjavascript:; stylefont-size: 16px;text-align: center;font-weight: normal;float: right idreg_mescode_btnableable clicksend_smscode${smscode_btn}/a
/p 8.1.2 register.js
check_smscode:function () {// 1.短信验证码格式校验let reg /^\d{6}$/;if (!reg.test(this.smscode)) {this.error_smscode true;} else {this.error_smscode false;}// 2.⼀致性校验if (!this.error_smscode) {axios.get(/check_smscode/ this.phone /?smscode this.smscode, {responseType: json}).then(response {let code response.data.code;if (code 4001 || code 4002 || code if (code 4001 || code 4002 || code 4003) {this.error_smscode true;this.error_smscode_msg response.data.errormsg;} else {this.error_smscode false;}})}
}
8.2 注册时短信验证后端逻辑
# verifications/views.py
class CheckSMScode(View):def get(self, request, phone):⽤户注册时短信验证码校验:param request::param phone::return:# 接收请求参数smscode_client request.GET.get(smscode, )# 校验参数if not all([phone, smscode_client]):return JsonResponse({code: 4001, errormsg: 缺少必传参数})# 查询服务器端短信验证码redis_conn django_redis.get_redis_connection(verify_code)smscode_server redis_conn.get(sms_%s % phone)# 匹配(⾮空判断/有效性判断)if smscode_server is None:return JsonResponse({code: 4002, errormsg: 短信验证码失效})smscode_server smscode_server.decode(utf-8)if smscode_client ! smscode_server:return JsonResponse({code: 4003, errormsg: 短信验证码不⼀致})# 响应结果return JsonResponse({code: 200, errormsg: OK})
9 避免频繁发送短信验证码
存在的问题
虽然我们在前端界⾯做了60秒倒计时功能。但是恶意⽤户可以 绕过前端界⾯向后端频繁请求短信验证码。
解决办法
在 后端也要限制 ⽤户请求短信验证码的频率。60秒内只允许⼀次请求短信 验证码。在Redis数据库中缓存⼀个数值有效期设置为60秒。 9.1 避免频繁发送短信验证码逻辑实现
9.1.1 提取并校验 is_send
is_send redis_conn.get(is_send_%s % phone)
if is_send:return JsonResponse({code: 4001, error_msg: 发送短信过于频繁})9.1.2 is_send 、smscode 存⼊redis数据库
# 保存短信验证码
redis_conn.setex(sms_%s % phone, 60, smscode)
# 保存is_send
redis_conn.setex(is_send_%s % phone, 60, 1)
9.1.3 界⾯渲染 频繁发送短信提示信息
if (response.data.code 4001) {this.error_smscode_msg response.data.error_msg;this.error_smscode_code true;
}