赞
踩
目录
要点
1. 保存短信验证码是为注册做准备的。
2. 为避免用户使用图形验证码恶意测试,后端提取了图形验证码后,立即删除图形验证码。
3. Django不具备发送短信的功能,所以我们借助第三方的短信平台来帮助我们发送短信验证码。
Python对接 阿里云短信平台_mengnf的专栏-CSDN博客
3.1 短信验证码接口设计
1. 请求方式
选项 方案 请求方法 GET 请求地址 /sms_codes/(?P<mobile>1[3-9]\d{9})/
2. 请求参数:路径参数和查询字符串
参数名 类型 是否必传 说明 mobile string 是 手机号 image_code string 是 图形验证码 uuid string 是 唯一编号
3. 响应结果:JSON
字段 说明 code 状态码 errmsg 错误信息
3.2 短信验证码接口定义(verifications\views.py)
- class SMSCodeView(View):
- """短信验证码"""
-
- def get(self, request, mobile):
- """
- :param mobile: 手机号
- :return: JSON
- """
- # 接受参数
- image_code_client = request.GET.get('image_code')
- uuid = request.GET.get('uuid')
-
- # 校验参数
- if not all([image_code_client, uuid]):
- return http.HttpResponseForbidden('缺少必传参数')
-
- # 创建连接到redis的对象
- redis_conn = get_redis_connection('verify_code')
-
- # 判断用户是否频繁发送短信验证码
- send_flag = redis_conn.get('send_flag_%s' % mobile)
- if send_flag:
- return http.JsonResponse({'code': RETCODE.THROTTLINGERR, 'errmsg': '发送短信过于频繁'})
-
- # 提取图形验证码
- image_code_server = redis_conn.get('img_%s' % uuid)
- if image_code_server is None:
- return http.JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码已失效'})
- # 删除图形验证码
- redis_conn.delete('img_%s' % uuid)
- # 对比图形验证码
- image_code_server = image_code_server.decode() # 将bytes转字符串,再比较
- if image_code_client.lower() != image_code_server.lower(): # 转小写,再比较
- return http.JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '输入图形验证码有误'})
-
- # 生成短信验证码:随机6位数字,000007
- sms_code = '%06d' % random.randint(0, 999999)
- logger.info(sms_code) # 手动的输出日志,记录短信验证码
-
- # # 保存短信验证码
- # redis_conn.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
- # # 保存发送短信验证码的标记
- # redis_conn.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
-
- # 创建redis管道
- pl = redis_conn.pipeline()
- # 将命令添加到队列中
- # 保存短信验证码
- pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
- # 保存发送短信验证码的标记
- pl.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
- # 执行
- pl.execute()
-
- # 发送短信验证码
- 这里调用发送短信的方法如:阿里云api.send(参数,,,)
-
- # 响应结果
- return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '发送短信成功'})
4.1 Vue绑定短信验证码界面
1.register.html
<li> <label>短信验证码:</label> <input type="text" v-model="sms_code" @blur="check_sms_code" name="sms_code" id="msg_code" class="msg_input"> <a @click="send_sms_code" class="get_msg_code">[[ sms_code_tip ]]</a> <span class="error_tip" v-show="error_sms_code">[[ error_sms_code_message ]]</span> {% if sms_code_errmsg %} <span class="error_tip">{{ sms_code_errmsg }}</span> {% endif %} </li>
2.register.js
check_sms_code(){ if(this.sms_code.length != 6){ this.error_sms_code_message = '请填写短信验证码'; this.error_sms_code = true; } else { this.error_sms_code = false; } },
4.2 axios请求短信验证码
1.发送短信验证码事件处理
// 发送短信验证码 send_sms_code() { // 避免恶意用户频繁的点击获取短信验证码的标签 if (this.send_flag == true) { // 先判断是否有人正在上厕所 return; // 有人正在上厕所,退回去 } this.send_flag = true; // 如果可以进入到厕所,立即关门 // 校验数据:mobile,image_code this.check_mobile(); this.check_image_code(); if (this.error_mobile == true || this.error_image_code == true) { this.send_flag = false; return; } let url = '/sms_codes/' + this.mobile + '/?image_code=' + this.image_code + '&uuid=' + this.uuid; 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 = '获取短信验证码'; // 还原sms_code_tip的提示文字 this.generate_image_code(); // 重新生成图形验证码 this.send_flag = false; } else { // 正在倒计时 num -= 1; // num = num - 1; this.sms_code_tip = num + '秒'; } }, 1000) } else { if (response.data.code == '4001') { // 图形验证码错误 this.error_image_code_message = response.data.errmsg; this.error_image_code = true; } else { // 4002 短信验证码错误 this.error_sms_code_message = response.data.errmsg; this.error_sms_code = true; } this.send_flag = false; } }) .catch(error => { console.log(error.response); this.send_flag = false; }) },
register.js完整代码:
- // 我们采用的时ES6的语法
- // 创建Vue对象 vm
- let vm = new Vue({
- el: '#app', // 通过ID选择器找到绑定的HTML内容
- // 修改Vue读取变量的语法
- delimiters: ['[[', ']]'],
- data: { // 数据对象
- // v-model
- username: '',
- password: '',
- password2: '',
- mobile: '',
- allow: '',
- image_code_url: '',
- uuid: '',
- image_code: '',
- sms_code_tip: '获取短信验证码',
- send_flag: false, // 类比上厕所,send_flag就是锁,false表示门开,true表示门关
- sms_code: '',
-
- // v-show
- error_name: false,
- error_password: false,
- error_password2: false,
- error_mobile: false,
- error_allow: false,
- error_image_code: false,
- error_sms_code: false,
-
- // error_message
- error_name_message: '',
- error_mobile_message: '',
- error_image_code_message: '',
- error_sms_code_message: '',
- },
- mounted() { // 页面加载完会被调用的
- // 生成图形验证码
- this.generate_image_code();
- },
- methods: { // 定义和实现事件方法
- // 发送短信验证码
- send_sms_code() {
- // 避免恶意用户频繁的点击获取短信验证码的标签
- if (this.send_flag == true) { // 先判断是否有人正在上厕所
- return; // 有人正在上厕所,退回去
- }
- this.send_flag = true; // 如果可以进入到厕所,立即关门
-
- // 校验数据:mobile,image_code
- this.check_mobile();
- this.check_image_code();
- if (this.error_mobile == true || this.error_image_code == true) {
- this.send_flag = false;
- return;
- }
-
- let url = '/sms_codes/' + this.mobile + '/?image_code=' + this.image_code + '&uuid=' + this.uuid;
- 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 = '获取短信验证码'; // 还原sms_code_tip的提示文字
- this.generate_image_code(); // 重新生成图形验证码
- this.send_flag = false;
- } else { // 正在倒计时
- num -= 1; // num = num - 1;
- this.sms_code_tip = num + '秒';
- }
- }, 1000)
- } else {
- if (response.data.code == '4001') { // 图形验证码错误
- this.error_image_code_message = response.data.errmsg;
- this.error_image_code = true;
- } else { // 4002 短信验证码错误
- this.error_sms_code_message = response.data.errmsg;
- this.error_sms_code = true;
- }
- this.send_flag = false;
- }
- })
- .catch(error => {
- console.log(error.response);
- this.send_flag = false;
- })
- },
- // 生成图形验证码的方法:封装的思想,代码复用
- generate_image_code() {
- this.uuid = generateUUID();
- this.image_code_url = '/image_codes/' + this.uuid + '/';
- },
- // 校验用户名
- check_username() {
- // 用户名是5-20个字符,[a-zA-Z0-9_-]
- // 定义正则
- let re = /^[a-zA-Z0-9_-]{5,20}$/;
- // 使用正则匹配用户名数据
- if (re.test(this.username)) {
- // 匹配成功,不展示错误提示信息
- this.error_name = false;
- } else {
- // 匹配失败,展示错误提示信息
- this.error_name_message = '请输入5-20个字符的用户名';
- this.error_name = true;
- }
-
- // 判断用户名是否重复注册
- if (this.error_name == false) { // 只有当用户输入的用户名满足条件时才回去判断
- let url = '/usernames/' + this.username + '/count/';
- axios.get(url, {
- responseType: 'json'
- })
- .then(response => {
- if (response.data.count == 1) {
- // 用户名已存在
- this.error_name_message = '用户名已存在';
- this.error_name = true;
- } else {
- // 用户名不存在
- this.error_name = false;
- }
- })
- .catch(error => {
- console.log(error.response);
- })
- }
- },
- // 校验密码
- check_password() {
- let re = /^[0-9A-Za-z]{8,20}$/;
- if (re.test(this.password)) {
- this.error_password = false;
- } else {
- this.error_password = true;
- }
- },
- // 校验确认密码
- check_password2() {
- if (this.password != this.password2) {
- this.error_password2 = true;
- } else {
- this.error_password2 = false;
- }
- },
- // 校验手机号
- check_mobile() {
- let re = /^1[3-9]\d{9}$/;
- if (re.test(this.mobile)) {
- this.error_mobile = false;
- } else {
- this.error_mobile_message = '您输入的手机号格式不正确';
- this.error_mobile = true;
- }
-
- // 判断手机号是否重复注册
- if (this.error_mobile == false) {
- let url = '/mobiles/' + this.mobile + '/count/';
- axios.get(url, {
- responseType: 'json'
- })
- .then(response => {
- if (response.data.count == 1) {
- this.error_mobile_message = '手机号已存在';
- this.error_mobile = true;
- } else {
- this.error_mobile = false;
- }
- })
- .catch(error => {
- console.log(error.response);
- })
- }
- },
- // 校验图形验证码吗
- check_image_code() {
- if (this.image_code.length != 4) {
- this.error_image_code_message = '请输入图形验证码';
- this.error_image_code = true;
- } else {
- this.error_image_code = false;
- }
- },
- // 校验短信验证码
- check_sms_code() {
- if (this.sms_code.length != 6) {
- this.error_sms_code_message = '请填写短信验证码';
- this.error_sms_code = true;
- } else {
- this.error_sms_code = false;
- }
- },
- // 校验是否勾选协议
- check_allow() {
- if (!this.allow) {
- this.error_allow = true;
- } else {
- this.error_allow = false;
- }
- },
- // 监听表单提交事件
- on_submit() {
- this.check_username();
- this.check_password();
- this.check_password2();
- this.check_mobile();
- this.check_sms_code();
- this.check_allow();
-
- // 在校验之后,注册数据中,只要有错误,就禁用掉表单的提交事件
- if (this.error_name == true || this.error_password == true || this.error_password2 == true || this.error_mobile == true || this.error_sms_code == true || this.error_allow == true) {
- // 禁用掉表单的提交事件
- window.event.returnValue = false;
- }
- },
- }
- });
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。