• Django商城项目笔记No.5用户部分-注册接口-短信验证码


    Django商城项目笔记No.4用户部分-注册接口-短信验证码

    短信验证码也保存在redis里(sms_code_15101234567)

    在views中新增SMSCodeView类视图,并且写出步骤如下:

    写逻辑

    因为这里要用到序列化器,所以就继承了GenericAPIView,这样的话,可以指定serializer_class,然后通过get_serializer就可以实例化序列化器了。

    注意 既然继承了GenericAPIView,那为啥不设置queryset属性,只设置了serializer_class属性了呢?

    这里用到谁,就设置谁。GenericAPIView没有要求必须都设置的。

    发送短信验证码序列化器实现

    让序列化器对于参数做校验,只校验image_code_id和text即可,手机号是在路由中,手机号不对的话也进不来这个视图函数

    最后一个逻辑,判断是否在60s内,是如何获取mobile的,分析如下:

    首先先来看下序列化器的context属性:

    在自己创建序列化器的时候,可以指定context,来传递数据。

    那么GenericAPIView提供的get_serializer方法在创建序列化器的时候,也指定了context,并且给context添加了三个数据:

    所以如下

    发送短信验证码视图实现

    发送间隔常量如下:

    send_flag标记问题

    控制前端请求过于频繁

    设置了send_flag标记之后,就算用户绕过前端,使用postman之类的工具,也无法频繁请求发送短信

     问题:那能不能不要这个标记,只存储sms_xxx行不行,利用他的有效期来处理这个逻辑行不?

    不行的,因为短信验证码的有效期是:5分钟。

    为什么短信验证码有效期是5分钟,自己思考

    使用云通讯发送短信验证码

    接下来发送短信验证码,但是需要用到云通讯的ccp,所以需要引入云通讯工具:

    将资料中的yuntongxun文件夹,直接copyutils

    然后修改一下配置信息:

     

    代码实现

    loger实现

    import logging
    logger = logging.getLogger('django')

    短信模板id

     

     url配置

     

    redis管道

    保存短信验证码和发送记录的时候,做了两次redis的操作

    改为管道

    补充删除图片验证码的逻辑

    避免用户拿着同一个图片验证码,获取多次短信验证码。

    如何避免呢?在获取到图片验证码之后,将redis中的图片验证码删除。

    发送短信前端代码说明与测试跨域请求

    发送短信验证码前端代码如下:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
        <title>美多商城-注册</title>
        <link rel="stylesheet" type="text/css" href="css/reset.css">
        <link rel="stylesheet" type="text/css" href="css/main.css">
        <script type="text/javascript" src="js/host.js"></script>
        <script type="text/javascript" src="js/vue-2.5.16.js"></script>
        <script type="text/javascript" src="js/axios-0.18.0.min.js"></script>
    </head>
    <body>
        <div class="register_con">
            <div class="l_con fl">
                <a class="reg_logo"><img src="images/logo.png"></a>
                <div class="reg_slogan">商品美 · 种类多 · 欢迎光临</div>
                <div class="reg_banner"></div>
            </div>
    
            <div class="r_con fr">
                <div class="reg_title clearfix">
                    <h1>用户注册</h1>
                    <a href="/login.html">登录</a>
                </div>
                <div class="reg_form clearfix" id="app" v-cloak>
                    <form id="reg_form" @submit.prevent="on_submit">
                    <ul>
                        <li>
                            <label>用户名:</label>
                            <input type="text" v-model="username" @blur="check_username" name="user_name" id="user_name">
                            <span v-show="error_name" class="error_tip">{{ error_name_message }}</span>
                        </li>                    
                        <li>
                            <label>密码:</label>
                            <input type="password" v-model="password" @blur="check_pwd" name="pwd" id="pwd">
                            <span v-show="error_password" class="error_tip">密码最少8位,最长20位</span>
                        </li>
                        <li>
                            <label>确认密码:</label>
                            <input type="password" v-model="password2" @blur="check_cpwd" name="cpwd" id="cpwd">
                            <span v-show="error_check_password" class="error_tip">两次输入的密码不一致</span>
                        </li>
                        <li>
                            <label>手机号:</label>
                            <input type="text" v-model="mobile" @blur="check_phone" name="phone" id="phone">
                            <span v-show="error_phone" class="error_tip">{{ error_phone_message }}</span>
                        </li>
                        <li>
                            <label>图形验证码:</label>
                            <input type="text" v-model="image_code" @blur="check_image_code" name="pic_code" id="pic_code" class="msg_input">
                            <img :src="image_code_url" @click="generate_image_code" alt="图形验证码" class="pic_code">
                            <span v-show="error_image_code" class="error_tip">{{ error_image_code_message }}</span>
                        </li>
                        <li>
                            <label>短信验证码:</label>
                            <input type="text" v-model="sms_code" @blur="check_sms_code" name="msg_code" id="msg_code" class="msg_input">
                            <a @click="send_sms_code" class="get_msg_code">{{ sms_code_tip }}</a>
                            <span v-show="error_sms_code" class="error_tip">{{ error_sms_code_message }}</span>
                        </li>
                        <li class="agreement">
                            <input type="checkbox" v-model="allow" @change="check_allow" name="allow" id="allow">
                            <label>同意”美多商城用户使用协议“</label>
                            <span v-show="error_allow" class="error_tip2">请勾选同意</span>
                        </li>
                        <li class="reg_sub">
                            <input type="submit" value="注 册" name="">
                        </li>
                    </ul>                
                    </form>
                </div>
    
            </div>
    
        </div>
    
        <div class="footer no-mp">
            <div class="foot_link">
                <a href="#">关于我们</a>
                <span>|</span>
                <a href="#">联系我们</a>
                <span>|</span>
                <a href="#">招聘人才</a>
                <span>|</span>
                <a href="#">友情链接</a>        
            </div>
            <p>CopyRight © 2016 北京美多商业股份有限公司 All Rights Reserved</p>
            <p>电话:010-****888    京ICP备*******8号</p>
        </div>
        <script type="text/javascript" src="js/register.js"></script>
    </body>
    </html>
    View Code

    register.js代码

    var vm = new Vue({
        el: '#app',
        data: {
            host: host,
    
            error_name: false,
            error_password: false,
            error_check_password: false,
            error_phone: false,
            error_allow: false,
            error_image_code: false,
            error_sms_code: false,
            error_name_message: '',
            error_image_code_message: '',
            error_phone_message: '',
            error_sms_code_message: '',
    
            image_code_id: '', // 图片验证码id
            image_code_url: '',
    
            sms_code_tip: '获取短信验证码',
            sending_flag: false, // 正在发送短信标志
    
            username: '',
            password: '',
            password2: '',
            mobile: '', 
            image_code: '',
            sms_code: '',
            allow: false
        },
        mounted: function(){
            this.generate_image_code();
        },
        methods: {
            // 生成uuid
            generate_uuid: function(){
                var d = new Date().getTime();
                if(window.performance && typeof window.performance.now === "function"){
                    d += performance.now(); //use high-precision timer if available
                }
                var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                    var r = (d + Math.random()*16)%16 | 0;
                    d = Math.floor(d/16);
                    return (c =='x' ? r : (r&0x3|0x8)).toString(16);
                });
                return uuid;
            },
            // 生成一个图片验证码的编号,并设置页面中图片验证码img标签的src属性
            generate_image_code: function(){
                // 生成一个编号
                // 严格一点的使用uuid保证编号唯一, 不是很严谨的情况下,也可以使用时间戳
                this.image_code_id = this.generate_uuid();
    
                // 设置页面中图片验证码img标签的src属性
                this.image_code_url = this.host + "/image_codes/" + this.image_code_id + "/";
            },
            check_username: function (){
                var len = this.username.length;
                if(len<5||len>20) {
                    this.error_name_message = '请输入5-20个字符的用户名';
                    this.error_name = true;
                } else {
                    this.error_name = false;
                }
    
            },
            check_pwd: function (){
                var len = this.password.length;
                if(len<8||len>20){
                    this.error_password = true;
                } else {
                    this.error_password = false;
                }        
            },
            check_cpwd: function (){
                if(this.password!=this.password2) {
                    this.error_check_password = true;
                } else {
                    this.error_check_password = false;
                }        
            },
            check_phone: function (){
                var re = /^1[345789]d{9}$/;
                if(re.test(this.mobile)) {
                    this.error_phone = false;
                } else {
                    this.error_phone_message = '您输入的手机号格式不正确';
                    this.error_phone = true;
                }
    
            },
            check_image_code: function (){
                if(!this.image_code) {
                    this.error_image_code_message = '请填写图片验证码';
                    this.error_image_code = true;
                } else {
                    this.error_image_code = false;
                }    
            },
            check_sms_code: function(){
                if(!this.sms_code){
                    this.error_sms_code_message = '请填写短信验证码';
                    this.error_sms_code = true;
                } else {
                    this.error_sms_code = false;
                }
            },
            check_allow: function(){
                if(!this.allow) {
                    this.error_allow = true;
                } else {
                    this.error_allow = false;
                }
            },
            // 发送手机短信验证码
            send_sms_code: function(){
                if (this.sending_flag == true) {
                    return;
                } 
                this.sending_flag = true;
    
                // 校验参数,保证输入框有数据填写
                this.check_phone();
                this.check_image_code();
    
                if (this.error_phone == true || this.error_image_code == true) {
                    this.sending_flag = false;
                    return;
                }
    
                // 向后端接口发送请求,让后端发送短信验证码
                axios.get(this.host + '/sms_codes/' + this.mobile + '/?text=' + this.image_code+'&image_code_id='+ this.image_code_id, {
                        responseType: 'json'
                    })
                    .then(response => {
                        // 表示后端发送短信成功
                        // 倒计时60秒,60秒后允许用户再次点击发送短信验证码的按钮
                        var num = 60;
                        // 设置一个计时器
                        var t = setInterval(() => {
                            if (num == 1) {
                                // 如果计时器到最后, 清除计时器对象
                                clearInterval(t);
                                // 将点击获取验证码的按钮展示的文本回复成原始文本
                                this.sms_code_tip = '获取短信验证码';
                                // 将点击按钮的onclick事件函数恢复回去
                                this.sending_flag = false;
                            } else {
                                num -= 1;
                                // 展示倒计时信息
                                this.sms_code_tip = num + '秒';
                            }
                        }, 1000, 60)
                    })
                    .catch(error => {
                        if (error.response.status == 400) {
                            this.error_image_code_message = '图片验证码有误';
                            this.error_image_code = true;
                            this.generate_image_code();
                        } else {
                            console.log(error.response.data);
                        }
                        this.sending_flag = false;
                    })
            },
            // 注册
            on_submit: function(){
                this.check_username();
                this.check_pwd();
                this.check_cpwd();
                this.check_phone();
                this.check_sms_code();
                this.check_allow();
    
    
            }
        }
    });
    View Code

    访问前端register.html,输入手机号和验证码,点击发送短信验证码,发现报错:

    缺少axios,那就copy一个过来:

    然后重新测试,报错信息如下:

     跨域请求未解决。

  • 相关阅读:
    OSG-提示“error reading file e:1.jpg file not handled”
    OSG-加载地球文件报0x00000005错误,提示error reading file simple.earth file not handled
    QT-找开工程后,最上方提示the code model could not parse an included file, which might lead to incorrect code completion and highlighting, for example.
    我的书《Unity3D动作游戏开发实战》出版了
    java中无符号类型的第三方库jOOU
    Windows批处理备份mysql数据
    使用 DevTools 时,通用Mapper经常会出现 class x.x.A cannot be cast to x.x.A
    Java版本,Java版本MongoDB驱动,驱动与MongoDB数据库,Spring之间的兼容性
    Jrebel本地激活方法
    wget下载指定网站目录下的所有内容
  • 原文地址:https://www.cnblogs.com/blog-rui/p/9739807.html
Copyright © 2020-2023  润新知