图片和短信验证码(头条项目-06)

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',),namespace='verify')),
# ⼦路由
re_path('^image_code/(?P<uuid>[\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, k=4)imgcode = "".join(random_str)# ⽣成图⽚验证码img = ImageCaptcha().generate(chars=imgcode)# 保存图⽚验证码到redisredis_conn = get_redis_connection('verify_code')redis_conn.setex('img_%s' % uuid, constants.IMAGE_CODE_REDIS_EXPIRES, imgcode)return http.HttpResponse(img, content_type='image/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 class="form-row form-row-wide"><input style="width: 250px;" placeholder="图⽚验证码"type="text" class="input-text"><img style="height: 40px;float: right;" :src="img_url"@click="generate_img_code"><span class="error-tip">图⽚验证码有误</span>
</p>
3.1.3 图形验证码展示和存储效果

3.2 Vue实现图形验证码校验

3.2.1 register.html
<p class="form-row form-row-wide"><input style="width: 250px;" placeholder="图⽚验证码" v-model='imgcode' @blur="check_imgcode" name="imgcode"type="text" class="input-text"><img style="height: 40px;float: right;" :src="img_url"@click="generate_img_code"><span class="error-tip" v-show="error_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: JSON"""pass

4.3 知识要点

  1. 保存短信验证码是为注册做准备的。
  2. 为了避免⽤户使⽤图形验证码恶意测试后端提取了图形验证码后,⽴即删除图形验证码
  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(url='https://106.ihuyi.com/webservice/sms.php?''method=Submit',data=urlencode(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, k=6)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 class="form-row form-row-wide"><input style="width: 250px;" placeholder="短信验证码" v-model='smscode'@blur="check_smscode" name="msgcode"type="text" class="input-text" id="reg_mescode"><span class="error-tip" v-show="error_code">${error_msgcode_msg}</span><a href="javascript:;" style="position: relative;left:150px;"@click="send_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 class="form-row form-row-wide"><input style="width: 230px;" v-model="smscode" placeholder="短信验证码"@blur="check_smscode" name="msgcode"type="text" class="input-text" id="reg_mescode"><span class="error-tip" v-show="error_smscode">${error_smscode_msg}</span><a href="javascript:;" style="font-size: 16px;text-align: center;font-weight: normal;float: right" id="reg_mescode_btn"able="able" @click="send_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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/67306.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云服务信息安全管理体系认证,守护云端安全

在数据驱动的时代&#xff0c;云计算已成为企业业务的超级引擎&#xff0c;推动着企业飞速发展。然而&#xff0c;随着云计算的广泛应用&#xff0c;信息安全问题也日益凸显&#xff0c;如同暗流涌动下的礁石&#xff0c;时刻威胁着企业的航行安全。这时&#xff0c;云服务信息…

LabVIEW与WPS文件格式的兼容性

LabVIEW 本身并不原生支持将文件直接保存为 WPS 格式&#xff08;如 WPS 文档或表格&#xff09;。然而&#xff0c;可以通过几种间接的方式实现这一目标&#xff0c;确保您能将 LabVIEW 中的数据或报告转换为 WPS 可兼容的格式。以下是几种常见的解决方案&#xff1a; ​ 导出…

创建 WordPress 插件(第一部分):添加管理页面

WordPress 是互联网上最受欢迎的内容管理系统之一。它是用 PHP 创建的&#xff0c;可以处理从博客到商业网站的一切需求。事实上&#xff0c;我们的博客和网站都使用 WordPress。在本文中&#xff0c;我将向你展示如何创建一个 WordPress 插件&#xff0c;该插件会在管理员控制…

解锁企业数据管理统一身份认证难题,EasyMR助力企业敏捷提效

在数字经济迅猛发展的当下&#xff0c;企业数据量正以令人惊叹的速度持续增长。据IDC研究显示&#xff0c;至2025年&#xff0c;全球数据总量预计将超175 ZB。数据的爆发式增长对企业而言&#xff0c;既是机遇&#xff0c;更是巨大挑战。 如今&#xff0c;大数据已然成为企业决…

OPT: Open Pre-trained Transformer语言模型

摘要 大规模语言模型通常需要数十万计算日的训练时间&#xff0c;展现了在零样本和小样本学习中的显著能力。鉴于其计算成本之高&#xff0c;这些模型在没有大量资本投入的情况下难以复现。对于那些通过API提供的少数模型&#xff0c;研究者无法获取完整的模型权重&#xff0c…

Qt应用之MDI(多文档设计)

qt creator 版本6.8.0 MinGW 64bit 由此模块可以扩展成设计一个qt文本编辑器。 界面如下 部分功能展示如下 新建文件 打开文件 mdi模式、级联模式和平铺模式 界面和程序构建过程。 1.如图所需.cpp和.h文件 2.mainwindow.ui和tformdoc.ui界面布局如下 不懂什么是Action如何…

Linux第二课:LinuxC高级 学习记录day04

6、shell中的语句 6.3、结构性语句 6.3.1、if if…then…fi 1、结构 1&#xff09;基本结构 if 表达式 then 命令表 fi if [ 表达式 ] // 【】两侧有空格 then 命令表 fi 2&#xff09;分层结构 if 表达式 then 命令表1 else 命令表2 fi 3&#xff09;嵌套结构 if …

Linux C 使用ZBar库解析二维码和条形码

1. 编译zbar库 下载 zbar 库源码&#xff0c;这里需要注意下&#xff0c;如果识别的二维码中有中文的话&#xff0c;会出现乱码&#xff0c;一般二维码里中文为UTF-8编码&#xff0c;zbar会默认给你把UTF-8转换为ISO8859-1。有两种解决办法&#xff0c;一是自己再转换一下编码…

【北京迅为】iTOP-4412全能版使用手册-第七十九章 Qt网络编程

iTOP-4412全能版采用四核Cortex-A9&#xff0c;主频为1.4GHz-1.6GHz&#xff0c;配备S5M8767 电源管理&#xff0c;集成USB HUB,选用高品质板对板连接器稳定可靠&#xff0c;大厂生产&#xff0c;做工精良。接口一应俱全&#xff0c;开发更简单,搭载全网通4G、支持WIFI、蓝牙、…

用python实战excel和word自动化

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 python实现excel和word自动化--批量处理 前言--需求快要期末了需要&#xff0c;提交一个年级的学生成绩数据&#xff0c;也就是几百份。当前我们收集了一份excel表格&#xf…

【R安装】R语言的详细安装及环境配置(2024年11月)

目录 R及Rstudio下载R下载Rstudio下载 R及Rstudio安装R安装Rtools 安装Rstudio安装 运行 RStudio通过RStudio配置使用特定的R版本 参考 R及Rstudio下载 R下载 R官网-The R Project for Statistical Computing 点击【download R】&#xff0c;进入下载界面&#xff1a; 选择…

Docker官网安装

1.官网 官方文档 https://www.docker.com/ Docker Hub官网 镜像 https://hub.docker.com/ 2.Docker 的三要素 1、镜像 2、容器 3、仓库 小总结 3.Docker 平台架构图 &#xff08;架构版本&#xff09; 4.安装Docker CentOS | Docker Docs 1.确定你是CentOS7及以上版本 …

寒假第一次牛客周赛 Round 76回顾

AC数&#xff1a;2&#xff08;A、C&#xff09; B 思路&#xff1a; 等价于求&#xff1a; 数量最多的字符 #include<stdio.h> int main() {int n,num;int a[26]{0};//用于存储字母 a 到 z 的出现次数。scanf("%d",&n);char s[n];scanf("%s",s)…

GARCH指导的神经网络在金融市场波动性预测中的应用

“GARCH-Informed Neural Networks for Volatility Prediction in Financial Markets” 论文地址&#xff1a;https://arxiv.org/pdf/2410.00288v1 摘要 波动性作为衡量风险的关键指标&#xff0c;广泛应用于金融投资的定价中。GARCH模型及其变体是用于股票波动性预测的传统工…

STM32-笔记43-低功耗

一、什么是低功耗&#xff1f; 低功耗‌是指通过优化设计和采用特定的技术手段&#xff0c;降低电子设备在运行过程中消耗的能量&#xff0c;从而延长电池寿命、提高性能和减少发热。低功耗设计主要从芯片设计和系统设计两个方面进行&#xff0c;旨在减少所有器件的功率损耗&am…

Docker 镜像制作原理 做一个自己的docker镜像

一.手动制作镜像 启动容器进入容器定制基于容器生成镜像 1.启动容器 启动容器之前我们首先要有一个镜像&#xff0c;这个镜像可以是从docker拉取&#xff0c;例如&#xff1a;现在pull一个ubuntu镜像到本机。 docker pull ubuntu:22.04 我们接下来可以基于这个容器进行容器…

辅助云运维

为客户提供运维支持&#xff0c;保障业务连续性。 文章目录 一、服务范围二、服务内容三、服务流程四、 服务交付件五、责任分工六、 完成标志 一、服务范围 覆盖范围 云产品使用咨询、问题处理、配置指导等&#xff1b; 云产品相关操作的技术指导&#xff1b; 云相关资源日常…

Vue3使用vue-count-to数字滚动模块报错解决方案

小伙伴们是不是遇到了vue3项目使用vue-count-to出现报错的问题 报错如下&#xff1a; TypeError: Cannot read properties of undefined (reading _c) 这个错误信息具体是说没读取到_c的属性 具体不清楚是什么原因&#xff0c;排查还得去看源码&#xff0c;所以我们来解决&a…

一分钟学习数据安全——数据安全的核心概念CIA以及安当解决方案

数据安全三要素是指保密性&#xff08;Confidentiality&#xff09;、完整性&#xff08;Integrity&#xff09;和可用性&#xff08;Availability&#xff09;&#xff0c;它们是信息安全领域的核心概念&#xff0c;旨在确保信息的安全和可信度。这边文章用一分钟的时间&#…

1️⃣Java中的集合体系学习汇总(List/Map/Set 详解)

目录 01. Java中的集合体系 02. 单列集合体系​ 1. Collection系列集合的遍历方式 &#xff08;1&#xff09;迭代器遍历&#xff08;2&#xff09;增强for遍历​编辑&#xff08;3&#xff09;Lambda表达式遍历 03.List集合详解 04.Set集合详解 05.总结 Collection系列…