vue_drf实现短信验证码

目录
  • 一、需求
    • 1,需求
  • 二、sdk参数配置  
    • 1,目录结构
  • 三、代码实现
    • 1,后端代码
    • 2,前端代码

一、需求

1,需求

  我们在做网站开发时,登录页面很多情况下是可以用手机号接收短信验证码,然后实现登录的,那我们今天就来做一做这一功能。

伪代码:

进入登录页面,点击短信登录
输入手机号码,点击获取验证码,后端在redis里保存验证码
用户把手机收到的验证码输入,点击登录,会把手机号和验证码发往后端,然后进行验证

要想发送短信,让用户收到短信,我们的借助一个容联云的接口,注册一个账号。

  使用时需要的一些参数:

  下载sdk

  1.。。。。。。。

  2.。。。。。。

  3.。。。。。。。

  下载完成后,解压。放入我们drf项目的apps里的libs里

二、sdk参数配置  

1,目录结构

  2,配置sms.py文件

# -*- coding:utf-8 -*-

from .CCPRestSDK import REST

# 说明:主账号,登陆云通讯网站后,可在"控制台-应用"中看到开发者主账号ACCOUNT SID
_accountSid = 'xxxxxxxxxxxxx'
# 8a216da863f8e6c20164139687e80c1b
# 说明:主账号Token,登陆云通讯网站后,可在控制台-应用中看到开发者主账号AUTH TOKEN
_accountToken = 'xxxxxxxxxxxxx'
# 6dd01b2b60104b3dbc88b2b74158bac6
# 请使用管理控制台首页的APPID或自己创建应用的APPID
_appId = '8aaf0708697b6beb01699f3c645f1766'
# 8a216da863f8e6c20164139688400c21
# 说明:请求地址,生产环境配置成app.cloopen.com
_serverIP = 'sandboxapp.cloopen.com'

# 说明:请求端口 ,生产环境为8883
_serverPort = "8883"

# 说明:REST API版本号保持不变
_softVersion = '2013-12-26'

#下面的内容不用修改
class CCP(object):
    """发送短信的辅助类"""

    def __new__(cls, *args, **kwargs):
        # 判断是否存在类属性_instance,_instance是类CCP的唯一对象,即单例
        if not hasattr(CCP, "_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, temp_id):
        """发送模板短信"""
        # @param to 手机号码
        # @param datas 内容数据 格式为数组 例如:{'12','34'},如不需替换请填 ''
        # @param temp_id 模板Id
        result = self.rest.sendTemplateSMS(to, datas, temp_id)
        # 如果云通讯发送短信成功,返回的字典数据result中statuCode字段的值为"000000"
        if result.get("statusCode") == "000000":
            # 返回0 表示发送短信成功
            return 0
        else:
            # 返回-1 表示发送失败
            return -1

if __name__ == '__main__':
    ccp = CCP()
    # 注意: 测试的短信模板编号为1
    ccp.send_template_sms('15914397060', ['1234', 5], 1)

三、代码实现

1,后端代码

  views.py,这是获取验证码请求的处理,也就是后端产生一个随机码,发送给手机用户,然后把随机码存储于redis中,然后给前端返回一个验证码发送成功的信号

from .models import User
from rest_framework import status
from lufei_drf.libs.yuntongxun.sms import CCP
from django_redis import get_redis_connection
class SMSCodeAPIView(APIView):
    def get(self,request):
        # 1. 通过查询字符串获取手机号码
        phone = request.query_params.get("phone")
        ty=request.query_params.get('type')
        # 2. 发送短信之前验证码验证一下手机号码
        if ty=='register':
            try:
                User.objects.get(phone=phone)
                return Response({"message": "当前手机号已经被注册过"}, status=status.HTTP_400_BAD_REQUEST)
            except:
                pass
        redis = get_redis_connection("sms_code")
        if redis.get("times_%s" % phone):
            return Response({"message": "当前手机号已经在一分钟内发送过短信"}, status=status.HTTP_400_BAD_REQUEST)

        # 3. 使用手机号码发送短信验证码
        # 生成一个短信验证码
        sms_code = "%04d" % random.randint(0, 9999)
        ccp = CCP()
        result = ccp.send_template_sms(phone,[sms_code,"5分钟"],1)

        if result == 0:
            # 发送短信成功,保存短信验证码到redis数据库中
            # 开启管道操作
            pl = redis.pipeline()
            pl.multi() # 接下来会在管道中执行多条命令
            # setex(变量名,有效期[秒],值 )
            SMS_EXPIRE_TIME = 5 * 60 # 短信验证码的有效期
            SMS_TIMES = 60  # 短信发送的间隔时间
            # 把原来立即执行的命令放置到管道
            pl.setex("sms_%s" % phone, SMS_EXPIRE_TIME, sms_code)
            pl.setex("times_%s" % phone, SMS_TIMES, 1)

            # 统一执行管道中的命令
            pl.execute()

        # 4. 响应数据给客户端
        return Response({"message":result},status=status.HTTP_200_OK)

  urls.py

from django.urls import path
# jwt内部实现的登陆视图
from rest_framework_jwt.views import obtain_jwt_token
from .views import SMSCodeAPIView,

urlpatterns=[
    path(r"login/", obtain_jwt_token ),
    path('sms/',SMSCodeAPIView.as_view()),
]

  utils.py,这是对用户提交手机验证码后,对手机号和验证码的校对。判断都正确后,返回一个对象,包括token,user信息等,

from django.contrib.auth.backends import ModelBackend
from django_redis import get_redis_connection

def jwt_response_payload_handler(token, user=None, request=None):
    """
    自定义jwt认证成功返回数据
    :token  返回的jwt
    :user   当前登录的用户信息[对象]
    :request 当前本次客户端提交过来的数据
    """
    return {
        'token': token,
        'id': user.id,
        'username': user.username,
    }

#实现多功能登录
import re
from .models import User#查找用户名或手机号是否已经是我们的用户
def get_user_by_account(account):
    """
    根据帐号获取user对象
    :param account: 账号,可以是用户名,也可以是手机号
    :return: User对象 或者 None
    """
    try:
        if re.match('^1[3-9]\d{9}$', account):
            # 帐号为手机号
            user = User.objects.get(phone=account)
        else:
            # 帐号为用户名
            user = User.objects.get(username=account)
    except User.DoesNotExist:
        return None
    else:
        return user
#验证用户提交的短信和我们保存在redis里的信息是否一致
def sms_code_verify(phone,sms_code):
    redis = get_redis_connection("sms_code")
    value=redis.get('sms_%s'%phone).decode()
    if value==sms_code:
        return True
    return False

class UsernameMobileAuthBackend(ModelBackend):
    """
    自定义用户名或手机号认证
    """
    def authenticate(self, request, username=None, password=None, **kwargs):
        user = get_user_by_account(username)      #当密码长度为4时,我判断其为手机号和短信验证码登录
        if len(password)==4 and user is not None and sms_code_verify(username,password):
            return user
        elif user is not None and user.check_password(password):
            return user
        else:
            return None

2,前端代码

login组件

<template>
  <div id="login">
    <div class="box">
      <p>
        <img src="../../assets/login_title.png" alt="">
      </p>
      <p class="sign">帮助有志向的年轻人通过努力学习获得体面的工作和生活!</p>
      <div class="pass" v-show="num==1">
        <div class="title2 cursor">
          <span @click="num=1" :class="num==1 ? 'show' :''">密码登录</span>    
          <span @click="num=2" :class="num==2 ? 'show' :''">短信登录</span>
        </div>
        <input v-model="username" type="text" class="ss" placeholder="用户名 / 手机号码">
        <input v-model="password" type="password" class="ss" placeholder="密码">
        <div id="captcha" class="ss"></div>
        <div class="t1">
          <div class="left">
            <input type="checkbox" class="cursor" v-model="remenber">
            <div class="remenber cursor" >记住密码</div>
          </div>
          <div class="right cursor">忘记密码</div>
        </div>
        <button class="login_btn" @click="login1">登录</button>
        <div class="register">
          没有账号
          <span><router-link to="/register">立即注册</router-link></span>
        </div>
      </div>
      <div class="messge" v-show="num==2">
        <div class="title2 cursor">
          <span @click="num=1" :class="num==1 ? 'show' :''">密码登录</span>    
          <span @click="num=2" :class="num==2 ? 'show' :''">短信登录</span>
        </div>
        <input v-model="phone" type="text" class="ss" placeholder="手机号码">
        <div class="sms">
          <input v-model="sms_code" type="text" class="ss">
          <div class="content" @click="get_sms_code">{{content}}</div>
        </div>
        <button class="login_btn" @click="sms_login">登录</button>
        <div class="register">
          没有账号
          <span><router-link to="/register">立即注册</router-link></span>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  export default {
    name:'login',
    data:function () {
      return {
        num:1,
        username:'',
        password:'',
        remenber:'',
        status:'',
        content:'获取验证码',
        phone:'',
        sms_code:'',
      }
    },
    methods:{
      //手机号和短信验证码登录
      sms_login:function(){
        let _this=this;
        this.$axios.post('http://127.0.0.1:8000/user/login/',{
            'username':_this.phone,
            'password':_this.sms_code,
          },{responseType:'json'})
          .then(function (res) {
            sessionStorage.token=res.data.token;
             _this.$router.go(-1);
          }).catch(function (error) {
          console.log(error.response)
        });
      },
      //获取短信验证码
      get_sms_code:function(){
        let reg = /1[3-9]{2}\d{8}/;
        if( reg.test(this.phone) ){
          if(this.content == "获取验证码"){
            this.content=60;
            let _this=this;
            let tt=setInterval(function () {
              if (_this.content>=1){
                _this.content--
              }
              else {
                _this.content='获取验证码';
                clearInterval(tt)
              }
            },1000);
            this.$axios.get('http://127.0.0.1:8000/user/sms?type=login&phone='+this.phone)
              .then(function (res) {
                if(res.data.message==0){
                  alert('验证码发送成功')
                }
              }).catch(function (error) {
                console.log(error.response)
              })
          }
        }else {
          alert('手机号码有误')
        }
      },
      //用户名和密码登录
      login1:function () {
        if (this.status==1){
          let _this=this;
          this.$axios.post('http://127.0.0.1:8000/user/login/',{
            'username':_this.username,
            'password':_this.password,
          },{responseType:'json'})
          .then(function (res) {
            if (res.status==200){
              if (_this.remenber){
                sessionStorage.removeItem('token');
                localStorage.token=res.data.token;
              }
              else {
                localStorage.removeItem('token');
                sessionStorage.token=res.data.token
              }
              _this.$router.go(-1);
            }
            else {
              alert('用户名或密码错误')
            }
          })
          .catch(function (error) {
            alert(error.response.data.non_field_errors[0]);
            console.log(error.response.data.non_field_errors);
          });
        }
        else {
          alert('验证码错误')
        }
      },
      handlerPopup:function (captchaObj) {
        let _this=this;
        captchaObj.onSuccess(function () {
           var validate = captchaObj.getValidate();
           _this.$axios.post("http://127.0.0.1:8000/user/yzm/",{
                    geetest_challenge: validate.geetest_challenge,
                    geetest_validate: validate.geetest_validate,
                    geetest_seccode: validate.geetest_seccode,
                },{
                  responseType:"json",
            }).then(function (res) {
              _this.status=res.data.status
           }).catch(function (error) {
             console.log(error)
           })
        });
        captchaObj.appendTo("#captcha");
      }
    },
    created:function () {
      let _this=this;
      this.$axios.get("http://127.0.0.1:8000/user/yzm")
        .then(function (res) {
          let data=JSON.parse(res.data);
          initGeetest({
                width:'350px',
                gt: data.gt,
                challenge: data.challenge,
                product: "popup",
                offline: !data.success
            }, _this.handlerPopup);
        }).catch(function (error) {
          console.log(error)
      })
    }

  }
</script>

<style scoped>
#login{
  background: url('../../assets/Login.jpg');
  background-size: 100% 100%;
  height: 100%;
  position: fixed;
  width: 100%;
}
.box{
  width: 500px;
  height: 600px;
  margin: 0 auto;
  margin-top: 200px;
  text-align: center;
}
.box img{
  width: 190px;
  height: auto;
}
.box p{
  margin: 0;
}
.sign{
  font-size: 18px;
  color: #fff;
  letter-spacing: .29px;
  padding-top: 10px;
  padding-bottom: 50px;
}
.pass{
  width: 400px;
  height: 460px;
  margin: 0 auto;
  background-color: white;
  border-radius: 4px;
}
.messge{
  width: 400px;
  height: 390px;
  margin: 0 auto;
  background-color: white;
  border-radius: 4px;
}
.title2{
  width: 350px;
  font-size: 20px;
  color: #9b9b9b;
  padding-top: 50px;
  border-bottom: 1px solid #e6e6e6;
  margin: 0 auto;
  margin-bottom: 20px;
}
.ss{
  width: 350px;
  height: 45px;
  border-radius: 4px;
  border: 1px solid #d9d9d9;
  text-indent: 20px;
  font-size: 14px;
  margin-bottom: 20px;
}
.pass .t1{
  width: 350px;
  margin: 0 auto;
  height: 20px;
  line-height: 20px;
  font-size: 12px;
  text-align: center;
  position: relative;
}
.t1 .right{
  position: absolute;
  right: 0;
}
.remenber{
  display: inline-block;
  position: absolute;
  left: 20px;
}
.left input{
  position: absolute;
  left:0;
  width: 14px;
  height: 14px;
}
.login_btn{
  width: 350px;
  height: 45px;
  background: #ffc210;
  border-radius: 5px;
  font-size: 16px;
  color: #fff;
  letter-spacing: .26px;
  margin-top: 30px;
  outline: none;
  border:none;
  cursor: pointer;
}
.register{
  margin-top: 20px;
  font-size: 14px;
  color: #9b9b9b;
}
.register span{
  color: #ffc210;
  cursor: pointer;
}
.cursor{
  cursor: pointer;
}
.show{
  display: inline-block;
  padding-bottom: 5px;
  border-bottom: 2px solid orange;
  color: #4a4a4a;
}
a{
  text-decoration: none;
  color: #ffc210;
}
#captcha{
  margin: 0 auto;
  height: 44px;
}
.sms{
  position: relative;
  width: 350px;
  height: 45px;
  margin: 0 auto;
  line-height: 45px;
}
.sms .content{
  position: absolute;
  top:0;
  right: 10px;
  color: orange;
  border-left: 1px solid orange;
  padding-left: 10px;
  cursor: pointer;

}
</style>

  前端获取短信验证码:

//获取短信验证码
      get_sms_code:function(){
        let reg = /1[3-9]{2}\d{8}/;    //当手机号为为真实手机号,才可以触发获取验证码
        if( reg.test(this.phone) ){    //当页面上显示为‘获取验证码'时,才可以触发获取验证码请求;当进入倒计时,点击不能触发获取验证码请求
          if(this.content == "获取验证码"){     //成功发送获取验证码请求之后开始倒计时60秒
            this.content=60;
            let _this=this;
            let tt=setInterval(function () {
              if (_this.content>=1){
                _this.content--
              }
              else {
                _this.content='获取验证码';
                clearInterval(tt)
              }
            },1000);
            this.$axios.get('http://127.0.0.1:8000/user/sms?type=login&phone='+this.phone)
              .then(function (res) {
                if(res.data.message==0){
                  alert('验证码发送成功')
                }
              }).catch(function (error) {
                console.log(error.response)
              })
          }
        }else {
          alert('手机号码有误')
        }
      },

  前端用手机号和短信验证码登录:

//获取短信验证码
      get_sms_code:function(){
        let reg = /1[3-9]{2}\d{8}/;    //当手机号为为真实手机号,才可以触发获取验证码
        if( reg.test(this.phone) ){    //当页面上显示为‘获取验证码'时,才可以触发获取验证码请求;当进入倒计时,点击不能触发获取验证码请求
          if(this.content == "获取验证码"){     //成功发送获取验证码请求之后开始倒计时60秒
            this.content=60;
            let _this=this;
            let tt=setInterval(function () {
              if (_this.content>=1){
                _this.content--
              }
              else {
                _this.content='获取验证码';
                clearInterval(tt)
              }
            },1000);
            this.$axios.get('http://127.0.0.1:8000/user/sms?type=login&phone='+this.phone)
              .then(function (res) {
                if(res.data.message==0){
                  alert('验证码发送成功')
                }
              }).catch(function (error) {
                console.log(error.response)
              })
          }
        }else {
          alert('手机号码有误')
        }
      },

到此这篇关于vue_drf实现短信验证码的文章就介绍到这了,更多相关vue_drf短信验证码内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 基于vue的短信验证码倒计时demo

    最近做了一个小的demo,分享给大家,在很多地方都能用到. 一般获取短信验证码的时候会用到这个demo: button里面包两个span标签,根据点击状态,显示不同的span,关键代码就是倒计时: <div id="example"> <button @click="send"> <span v-if="sendMsgDisabled">{{time+'秒后获取'}}</span> <span

  • Vue 短信验证码组件开发详解

    Vue.js(读音 /vjuː/, 类似于 view)是一个构建数据驱动的 web 界面的库.Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件. Vue.js 自身不是一个全能框架--它只聚焦于视图层.因此它非常容易学习,非常容易与其它库或已有项目整合.另一方面,在与相关工具和支持库一起使用时,Vue.js 也能完美地驱动复杂的单页应用. 摘要: 1.该组件基于Vue 2.1.X版本: 1. Vue 组件代码如下: Vue.component('timerBtn

  • Vue.js实现移动端短信验证码功能

    现在的短信验证码一般为4位或6位,则页面中会相应的显示4个或6个文本框,如图所示 当点击注册进入到输入验证码页面的时候,第一个框自动获取光标,依次输入,不可直接输入第三个或第四个框的值, input输入框是循环出来的,代码如下: <div class="sms_input"> <div v-for="n in sms.numbers-1"><input v-if="sms.show[n-1]" disabled=&q

  • vue实现短信验证码输入框

    本文实例为大家分享了vue实现短信验证码输入框的具体代码,供大家参考,具体内容如下 先上最终效果 (此处代码显示的是短信验证码框的效果   其余部分并未放上去) html <div class="code"> <input id="first" class="inputStyle" v-model="code[0]" style="border-top-left-radius: 12px; bord

  • vue 实现通过手机发送短信验证码注册功能

    效果如下: 代码如下: template代码: <el-main> <el-form :model="ReginForm" ref="ReginForm" :rules="rule" class="regform" label-width="0"> <h3 class="login-text">手机注册</h3> <el-form-i

  • vue_drf实现短信验证码

    目录 一.需求 1,需求 二.sdk参数配置 1,目录结构 三.代码实现 1,后端代码 2,前端代码 一.需求 1,需求 我们在做网站开发时,登录页面很多情况下是可以用手机号接收短信验证码,然后实现登录的,那我们今天就来做一做这一功能. 伪代码: 进入登录页面,点击短信登录 输入手机号码,点击获取验证码,后端在redis里保存验证码 用户把手机收到的验证码输入,点击登录,会把手机号和验证码发往后端,然后进行验证 要想发送短信,让用户收到短信,我们的借助一个容联云的接口,注册一个账号. 使用时需要

  • 使用 laravel sms 构建短信验证码发送校验功能

    laravel 实现短信验证码功能,搜索资料发现比较流行的有两个包: 一个是laravel sms 地址  https://github.com/toplan/laravel-sms 一个是easy sms 地址https://github.com/overtrue/easy-sms, 项目中需要实现一个发送和验证短信验证码的功能.以前的办法稍显繁琐.经高人指点,发现可以用 laravel-sms 这个包替代.且配置和使用简单易学.故有了这篇示例. 本例使用了Laravel 5.5. Api S

  • 在 Laravel 中 “规范” 的开发短信验证码发送功能

    Laravel简介 Laravel是一套简洁.优雅的PHP Web开发框架(PHP Web Framework).它可以让你从面条一样杂乱的代码中解脱出来:它可以帮你构建一个完美的网络APP,而且每行代码都可以简洁.富于表达力. 在Laravel中已经具有了一套高级的PHP ActiveRecord实现 -- Eloquent ORM.它能方便的将"约束(constraints)"应用到关系的双方,这样你就具有了对数据的完全控制,而且享受到ActiveRecord的所有便利.Eloqu

  • Android开发中通过手机号+短信验证码登录的实例代码

    首先,需要一个电话号码,目前很多账户都是将账户名设置成手机号,然后点击按钮获取手机验证码. 其次,你需要后台给你手机短信的验证接口,各个公司用的不一样,这个身为前端,不需要你来考虑,你只要让你后台给你写好接口,你直接调用就好了. activity_login.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.andr

  • JS实现用户注册时获取短信验证码和倒计时功能

    在用户注册时,通常需要短信验证码,而且为了交互效果,也需要增加倒计时. 效果如下: <div class="user-form"> <form action="{{ path('zm_member_register') }}" method="post"> <div class="form-list"> <label class="register-label"&g

  • js验证手机号、密码、短信验证码代码工具类

    本文实例为大家分享了js验证手机号.密码.短信验证码的代码工具类,供大家参考,具体内容如下 代码工具类 /** * 参数较验 * * */ var verification = { stop : false, //倒计时 //验证手机号 phone : function (tel, id) { if ("" == tel || !tel) { mui.toast('手机号不可以为空!'); } else { var reg = /^0?1[3|4|5|7|8][0-9]\d{8}$/;

  • Nodejs 发送Post请求功能(发短信验证码例子)

    直接上代码 sms.js var http = require('http'); var querystring = require('querystring'); function SmsCode() { //发短信 this.send = function (req0, res0) { var code = "3212"; var txt = "您的验证码是:"+code+".请不要把验证码泄露给其他人.如非本人操作,可不用理会!"; var

  • 基于JAVA的短信验证码api调用代码实例

    本文实例为大家分享了JAVA的短信验证码api调用代码,供大家参考,具体内容如下 import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import jav

  • JAVA实现利用第三方平台发送短信验证码

    前段时间自己做的一个小项目中,涉及到用短信验证码登录.注册的问题,之前没涉及过这一块,看了别人的博客其实也是似懂非懂的,现在就将自己做的利用第三方短信平台来发送验证码这个功能记下来. 本文以注册为例,在SpringMVC+Spring+Mybatis框架的基础上完成该短信验证码功能. 发送短信验证码的原理是:随机生成一个6位数字,将该6位数字保存到session当中,客户端通过sessionid判断对应的session,用户输入的验证码再与session记录的验证码进行比较. 为了防止有广告嫌疑

  • Java随机生成手机短信验证码的方法

    本文实例讲述了Java随机生成手机短信验证码的方法.分享给大家供大家参考,具体如下: /** * 创建指定数量的随机字符串 * @param numberFlag 是否是数字 * @param length * @return */ public static String createRandom(boolean numberFlag, int length){ String retStr = ""; String strTable = numberFlag ? "1234

随机推荐