vue_drf implements SMS verification code

vue_drf implements SMS verification code

1. Demand

1. Demand

When we are developing a website, in many cases the login page can use a mobile phone number to receive a text message verification code and then log in. Let's do this function today.

pseudocode:

Enter the login page, click SMS login, enter the mobile phone number, click Get verification code, the backend saves the verification code in redis. The user enters the verification code received on the mobile phone, clicks Login, and the mobile phone number and verification code will be sent to the backend for verification.

In order to send text messages and let users receive text messages, we use the RongCloud interface to register an account.

Some parameters required for use:

Download SDK

1. . . . . . .

2. . . . . .

3. . . . . . .

After downloading, unzip it. Put it in libs in apps of our drf project

2. SDK parameter configuration

1. Directory structure

2. Configure the sms.py file

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

from .CCPRestSDK import REST

# Note: After logging into the cloud communication website, you can see the developer's main account ACCOUNT SID in "Console-Application".
_accountSid = 'xxxxxxxxxxxxx'
# 8a216da863f8e6c20164139687e80c1b
# Description: The main account Token, after logging in to the cloud communication website, you can see the developer's main account AUTH TOKEN in the console-application
_accountToken = 'xxxxxxxxxxxxxxx'
# 6dd01b2b60104b3dbc88b2b74158bac6
# Please use the APPID on the homepage of the management console or the APPID of the application you created yourself
_appId = '8aaf0708697b6beb01699f3c645f1766'
# 8a216da863f8e6c20164139688400c21
# Note: Request address. The production environment is configured as app.cloopen.com
_serverIP = 'sandboxapp.cloopen.com'

# Description: Request port, the production environment is 8883
_serverPort = "8883"

# Note: The REST API version number remains unchanged_softVersion = '2013-12-26'

#The following content does not need to be modified class CCP(object):
    """Auxiliary class for sending SMS messages"""

    def __new__(cls, *args, **kwargs):
        # Check if there is a class attribute _instance. _instance is the only object of class CCP, i.e. a singleton 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):
        """Send template SMS"""
        # @param to mobile phone number # @param datas The content data format is an array, for example: {'12','34'}, if no replacement is required, please fill in ''
        # @param temp_id Template ID
        result = self.rest.sendTemplateSMS(to, datas, temp_id)
        # If Cloud Communication sends the SMS successfully, the value of the statuCode field in the returned dictionary data result is "000000"
        if result.get("statusCode") == "000000":
            # Return 0 means the SMS message was sent successfully return 0
        else:
            # Return -1 means sending failed return -1


if __name__ == '__main__':
    ccp = CCP()
    # Note: The SMS template number for the test is 1
    ccp.send_template_sms('15914397060', ['1234', 5], 1)

3. Code Implementation

1. Backend code

views.py, this is the processing of obtaining verification code requests, that is, the backend generates a random code, sends it to the mobile phone user, then stores the random code in redis, and then returns a verification code sending success signal to the front end

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. Get the phone number through the query string phone = request.query_params.get("phone")
        ty = request.query_params.get('type')
        # 2. Verify the mobile number with the verification code before sending the SMS if ty=='register':
            try:
                User.objects.get(phone=phone)
                return Response({"message": "The current phone number has been registered"}, status=status.HTTP_400_BAD_REQUEST)
            except:
                pass
        redis = get_redis_connection("sms_code")
        if redis.get("times_%s" % phone):
            return Response({"message": "The current phone number has sent a text message within one minute"}, status=status.HTTP_400_BAD_REQUEST)

        # 3. Use the mobile phone number to send a text message verification code# Generate a text message verification code sms_code = "%04d" % random.randint(0, 9999)
        ccp = CCP()
        result = ccp.send_template_sms(phone,[sms_code,"5 minutes"],1)

        if result == 0:
            #Send SMS successfully, save SMS verification code to redis database#Open pipeline operation pl = redis.pipeline()
            pl.multi() # Next, multiple commands will be executed in the pipeline # setex(variable name, validity period [seconds], value)
            SMS_EXPIRE_TIME = 5 * 60 # The validity period of the SMS verification code SMS_TIMES = 60 # The interval between SMS sending # Put the original immediately executed command into the pipeline pl.setex("sms_%s" % phone, SMS_EXPIRE_TIME, sms_code)
            pl.setex("times_%s" % phone, SMS_TIMES, 1)

            # Unify the execution of commands in the pipeline pl.execute()

        # 4. Response data to the client return Response({"message":result},status=status.HTTP_200_OK)

urls.py

from django.urls import path
# Login view implemented internally by 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, this is to check the mobile phone number and verification code after the user submits the mobile phone verification code. After all the judgments are correct, an object is returned, including token, user information, etc.

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


def jwt_response_payload_handler(token, user=None, request=None):
    """
    Custom jwt authentication successfully returns data: jwt returned by token
    :user Current logged in user information [object]
    :request The data currently submitted by the client"""
    return {
        'token': token,
        'id': user.id,
        'username': user.username,
    }

#Realize multi-function login import re
from .models import User#Find out if the username or phone number is already our user def get_user_by_account(account):
    """
    Get the user object based on the account:param account: account, which can be a username or a phone number:return: User object or None
    """
    try:
        if re.match('^1[3-9]\d{9}$', account):
            # The account is a mobile phone number user = User.objects.get(phone=account)
        else:
            # The account is the username user = User.objects.get(username=account)
    except User.DoesNotExist:
        return None
    else:
        return user
#Verify whether the SMS message submitted by the user is consistent with the information we saved in 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):
    """
    Customize username or phone number authentication"""
    def authenticate(self, request, username=None, password=None, **kwargs):
        user = get_user_by_account(username) #When the password length is 4, I judge it to be a mobile phone number and SMS verification code login 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. Front-end code

login component

<template>
  <div id="login">
    <div class="box">
      <p>
        <img src="../../assets/login_title.png" alt="">
      </p>
      <p class="sign">Help ambitious young people get a decent job and life through hard study! </p>
      <div class="pass" v-show="num==1">
        <div class="title2 cursor">
          <span @click="num=1" :class="num==1 ? 'show' :''">Password login</span>
              <span @click="num=2" :class="num==2 ? 'show' :''">SMS login</span>
        </div>
        <input v-model="username" type="text" class="ss" placeholder="Username/Mobile number">
        <input v-model="password" type="password" class="ss" placeholder="password">
        <div id="captcha" class="ss"></div>
        <div class="t1">
          <div class="left">
            <input type="checkbox" class="cursor" v-model="remenber">
            <div class="remenber cursor" >Remember password</div>
          </div>
          <div class="right cursor">Forgot password</div>
        </div>
        <button class="login_btn" @click="login1">Login</button>
        <div class="register">
          No account<span><router-link to="/register">Register now</router-link></span>
        </div>
      </div>
      <div class="message" v-show="num==2">
        <div class="title2 cursor">
          <span @click="num=1" :class="num==1 ? 'show' :''">Password login</span>
              <span @click="num=2" :class="num==2 ? 'show' :''">SMS login</span>
        </div>
        <input v-model="phone" type="text" class="ss" placeholder="Phone number">
        <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">Login</button>
        <div class="register">
          No account<span><router-link to="/register">Register now</router-link></span>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  export default {
    name:'login',
    data:function () {
      return {
        num:1,
        username:'',
        password:'',
        remenber:'',
        status:'',
        content:'Get verification code',
        phone:'',
        sms_code:'',
      }
    },
    methods:{
      //Mobile phone number and SMS verification code login 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 verification codeget_sms_code:function(){
        let reg = /1[3-9]{2}\d{8}/;
        if( reg.test(this.phone) ){
          if(this.content == "Get verification code"){
            this.content=60;
            let _this=this;
            let tt = setInterval(function () {
              if (_this.content>=1){
                _this.content--
              }
              else {
                _this.content='Get verification code';
                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('Verification code sent successfully')
                }
              }).catch(function (error) {
                console.log(error.response)
              })
          }
        }else {
          alert('The mobile phone number is incorrect')
        }
      },
      //Username and password 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('Incorrect username or password')
            }
          })
          .catch(function (error) {
            alert(error.response.data.non_field_errors[0]);
            console.log(error.response.data.non_field_errors);
          });
        }
        else {
          alert('Verification code error')
        }
      },
      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;
}
.message{
  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>

The front end obtains the SMS verification code:

//Get SMS verification codeget_sms_code:function(){
        let reg = /1[3-9]{2}\d{8}/; //When the phone number is a real phone number, the verification code can be obtained if( reg.test(this.phone) ){ //When the page displays 'Get Verification Code', the verification code request can be triggered; when the countdown begins, clicking cannot trigger the verification code request if(this.content == "Get Verification Code"){ //After successfully sending the verification code request, the countdown starts for 60 seconds this.content=60;
            let _this=this;
            let tt = setInterval(function () {
              if (_this.content>=1){
                _this.content--
              }
              else {
                _this.content='Get verification code';
                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('Verification code sent successfully')
                }
              }).catch(function (error) {
                console.log(error.response)
              })
          }
        }else {
          alert('The mobile phone number is incorrect')
        }
      },

The front end uses the mobile phone number and SMS verification code to log in:

//Get SMS verification codeget_sms_code:function(){
        let reg = /1[3-9]{2}\d{8}/; //When the phone number is a real phone number, the verification code can be obtained if( reg.test(this.phone) ){ //When the page displays 'Get Verification Code', the verification code request can be triggered; when the countdown begins, clicking cannot trigger the verification code request if(this.content == "Get Verification Code"){ //After successfully sending the verification code request, the countdown starts for 60 seconds this.content=60;
            let _this=this;
            let tt = setInterval(function () {
              if (_this.content>=1){
                _this.content--
              }
              else {
                _this.content='Get verification code';
                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('Verification code sent successfully')
                }
              }).catch(function (error) {
                console.log(error.response)
              })
          }
        }else {
          alert('The mobile phone number is incorrect')
        }
      },

This is the end of this article about vue_drf implementing SMS verification code. For more relevant vue_drf SMS verification code content, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Implementation of vue+drf+third-party sliding verification code access

<<:  Solution to the problem that Java cannot connect to MySQL 8.0

>>:  How to deploy your first application with Docker

Recommend

A complete guide to the Docker command line (18 things you have to know)

Preface A Docker image consists of a Dockerfile a...

Basic usage of UNION and UNION ALL in MySQL

In the database, both UNION and UNION ALL keyword...

HTML Basics: The basic structure of HTML

The basic structure of HTML hypertext documents is...

A brief discussion on the magical slash in nginx reverse proxy

When configuring nginx reverse proxy, the slashes...

How to use the Clipboard API in JS

Table of contents 1. Document.execCommand() metho...

MySQL table name case selection

Table of contents 1. Parameters that determine ca...

Detailed steps to delete environment variables in Linux

How to delete environment variables in Linux? Use...

Implementing carousel effects with JavaScript

This article shares the specific code for JavaScr...

MySQL slow query method and example

1. Introduction By enabling the slow query log, M...

Implementing a shopping cart with native JavaScript

This article shares the specific code of JavaScri...

Detailed explanation of Vue project packaging

Table of contents 1. Related configuration Case 1...

JS implements random roll call system

Use JS to implement a random roll call system for...