一.逻辑分析
整体思路:(以下代码块都为伪代码)
1,当前端按下获取验证码按钮的时候,执行js文件中的send_sms_code方法,send_sms_code方法中,向后端发送请求。
2,发送的请求应该包括电话号码,uuid,图片验证码,uuid是为了验证图片验证码
同时因为需求是要求点击了按钮之后,按钮的显示变成六十秒倒计时,所以是局部刷新,应该是ajax请求
3,从redis数据库中提取图形验证码,提取到图形验证码后删除图形验证码,避免因为恶意用户在图形验证码刷新之后仍然使用之前未过期的图形验证码
4,生成随机的六位数验证码,保存到redis数据库
5,和第三方软件容联云进行导入,实现发送手机验证码功能
二. 前端的实现(ajax请求)
send_sms_code(){
let url = '/sms_codes/' + this.mobile + '/?image_code=' + this.image_code+'&uuid='+ this.uuid+'&sms_code'+this.sms_code;
axios.get(url,{
responseType:'json'
})
.then(response => {
if(response.data.code == 0){
//展示倒计时60秒
let num = 60;
let t = setInterval(()=>{
if (num == 1){
//倒计时即将结束,停止回调函数
clearInterval(t);
this.sms_code_tip = '获取短信验证码'
// 重新刷新图片验证码
this.generate_image_code();
this.send_flag = false;
}else{
// 初始化计时器
num = num-1;
this.sms_code_tip = num+'秒';
}
},1000) // 回调函数,时间间隔
}else{
if(response.data.code == 4001){
//图形验证码错误
this.error_image_code_message = response.data.error;
this.error_msg_code = true;
this.send_flag = false;
}
//
}
})
.catch(error=>{
console.log(error.response)
this.send_flag = false;
})
},
三.接受请求
在django中子应用中设置url接受请求地址,设置视图,实现后端逻辑,电话号码使用正则表达式从前端直接提取到,uuid和图形验证码通过?key=value的方法,利用关键字然后get得到。
class SMSCodeVies(View):
def get(self, request, mobile):
# 接收参数(uuid,mobile,image_code
uuid = request.GET.get('uuid')
image_code_client = request.GET.get('image_code')
四.得到系统生成的图形验证码
# 1,创建redis连接对象,先导入get_redis_connection
from django_redis import get_redis_connection
redis_conn = get_redis_connection('verify_code')`
# 参数为Redis的库别名
# 2,`利用关键字,得到之前保存的图形验证码,key值为'img_%s' % uuid,是之前在建立图形验证码的时候设置的保存进入redis数据库中的
image_code_server = redis_conn.get('img_%s' % uuid)
# 3, 删除图形验证码
redis_conn.delete('img_%s' % uuid)
# 4, 对比图形验证码
# 因为从redis中取出来的数据为byte数据类型,为了对比用户输入的图形验证码,转换为string数据类型
image_code_server = image_code_server.decode()
if image_code_server.lower() != image_code_client.lower():
return http.JsonResponse({'code': RETCODE.IMAGECODEERR, 'error':'图形验证码有误'})
五.生成短信验证码
# 如果生成不足六位的数字,则往前面补零形成六位字符串
sms_code = '%06d' % random.randint(0, 999999)
redis_conn.setex('sms_%s'% mobile,constants.SMS_CODE_REDIS_EXPIRES,sms_code)
六.发送短信验证码
# -*- coding:utf-8 -*-
# import ssl
# ssl._create_default_https_context =ssl._create_stdlib_context # 解决Mac开发环境下,网络错误的问题
from verifications.libs.yuntongxun.CCPRestSDK import REST
# 说明:主账号,登陆云通讯网站后,可在"控制台-应用"中看到开发者主账号ACCOUNT SID
_accountSid = '8a216da878005a800178bbcbfe3e4555'
# 说明:主账号Token,登陆云通讯网站后,可在控制台-应用中看到开发者主账号AUTH TOKEN
_accountToken = '1ecddaae6aec4ba88083d46942056a4b'
# 请使用管理控制台首页的APPID或自己创建应用的APPID
_appId = '8a216da878005a800178bbcbff29455c'
# 说明:请求地址,生产环境配置成app.cloopen.com
_serverIP = 'app.cloopen.com'
# 说明:请求端口 ,生产环境为8883
_serverPort = "8883"
# 说明:REST API版本号保持不变
_softVersion = '2013-12-26'
# 云通讯官方提供的发送短信代码实例
# 发送模板短信
# @param to 手机号码
# @param datas 内容数据 格式为数组 例如:{'12','34'},如不需替换请填 ''
# @param $tempId 模板Id
# def sendTemplateSMS(to, datas, tempId):
# # 初始化REST SDK
# rest = REST(_serverIP, _serverPort, _softVersion)
# rest.setAccount(_accountSid, _accountToken)
# rest.setAppId(_appId)
#
# result = rest.sendTemplateSMS(to, datas, tempId)
# print(result)
class CCP(object):
# 发送短信验证码的单例类
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
# 单例类
cls._instance = super(CCP, cls).__new__(cls, *args, **kwargs)
cls._instance.rest = REST(_serverIP, _serverPort, _softVersion)
cls._instance.rest.setAccount(_accountSid, _accountToken)
cls._instance.rest.setAppId(_appId)
return cls._instance
def send_template_sms(self,to, datas, tempId):
"""
:param to: 电话号码
:param datas:内容数据
:param tempId:模板id
:return:成功返回0,失败返回-1
"""
result = self.rest.sendTemplateSMS(to, datas, tempId)
print(result)
if result.get('statusCode') == '000000':
return 0
else:
return -1
从容联云提供的文档中下载到ccp_sms.py文件中更新自己的容联云信息,包装发送短信的CCP单类,将其导入到view中进行调用