Old Boy Python Notes _74_User Registration Authentication _Implementation of Registration Function _Cloud Communication Sending Short Message Verification Code

Keywords: Mobile Redis Django Database

Articles Catalogue

User Registration and Authentication

Front-end display registration page

Adjust the link between the header of the home page and the registration button of the landing page.

Registration page Register, mainly through the login page to change.

<template>
	<div class="box">
		<img src="/static/image/Loginbg.3377d0c.jpg" alt="">
		<div class="register">
			<div class="register_box">
        <div class="register-title">Registered Lufei School Town</div>
				<div class="inp">
					<input v-model="mobile" type="text" placeholder="Phone number" class="user">
          <input v-model="password" type="password" placeholder="Input password" class="user">
					<input v-model="sms" type="text" placeholder="Input Verification Code" class="user">
          <div id="geetest"></div>
					<button class="register_btn" >register</button>
					<p class="go_login" >Existing accounts <router-link to="/user/login">Direct login</router-link></p>
				</div>
			</div>
		</div>
	</div>
</template>

<script>
export default {
  name: 'Register',
  data(){
    return {
        sms:"",
        mobile:"",
        validateResult:false,
    }
  },
  created(){
  },
  methods:{},

};
</script>

<style scoped>
.box{
	width: 100%;
  height: 100%;
	position: relative;
  overflow: hidden;
}
.box img{
	width: 100%;
  min-height: 100%;
}
.box .register {
	position: absolute;
	width: 500px;
	height: 400px;
	left: 0;
  margin: auto;
  right: 0;
  bottom: 0;
  top: -338px;
}
.register .register-title{
    width: 100%;
    font-size: 24px;
    text-align: center;
    padding-top: 30px;
    padding-bottom: 30px;
    color: #4a4a4a;
    letter-spacing: .39px;
}
.register-title img{
    width: 190px;
    height: auto;
}
.register-title p{
    font-size: 18px;
    color: #fff;
    letter-spacing: .29px;
    padding-top: 10px;
    padding-bottom: 50px;
}
.register_box{
    width: 400px;
    height: auto;
    background: #fff;
    box-shadow: 0 2px 4px 0 rgba(0,0,0,.5);
    border-radius: 4px;
    margin: 0 auto;
    padding-bottom: 40px;
}
.register_box .title{
	font-size: 20px;
	color: #9b9b9b;
	letter-spacing: .32px;
	border-bottom: 1px solid #e6e6e6;
	 display: flex;
    	justify-content: space-around;
    	padding: 50px 60px 0 60px;
    	margin-bottom: 20px;
    	cursor: pointer;
}
.register_box .title span:nth-of-type(1){
	color: #4a4a4a;
    	border-bottom: 2px solid #84cc39;
}

.inp{
	width: 350px;
	margin: 0 auto;
}
.inp input{
    outline: 0;
    width: 100%;
    height: 45px;
    border-radius: 4px;
    border: 1px solid #d9d9d9;
    text-indent: 20px;
    font-size: 14px;
    background: #fff !important;
}
.inp input.user{
    margin-bottom: 16px;
}
.inp .rember{
     display: flex;
    justify-content: space-between;
    align-items: center;
    position: relative;
    margin-top: 10px;
}
.inp .rember p:first-of-type{
    font-size: 12px;
    color: #4a4a4a;
    letter-spacing: .19px;
    margin-left: 22px;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-align: center;
    align-items: center;
    /*position: relative;*/
}
.inp .rember p:nth-of-type(2){
    font-size: 14px;
    color: #9b9b9b;
    letter-spacing: .19px;
    cursor: pointer;
}

.inp .rember input{
    outline: 0;
    width: 30px;
    height: 45px;
    border-radius: 4px;
    border: 1px solid #d9d9d9;
    text-indent: 20px;
    font-size: 14px;
    background: #fff !important;
}

.inp .rember p span{
    display: inline-block;
  font-size: 12px;
  width: 100px;
  /*position: absolute;*/
/*left: 20px;*/

}
#geetest{
	margin-top: 20px;
}
.register_btn{
     width: 100%;
    height: 45px;
    background: #84cc39;
    border-radius: 5px;
    font-size: 16px;
    color: #fff;
    letter-spacing: .26px;
    margin-top: 30px;
}
.inp .go_login{
    text-align: center;
    font-size: 14px;
    color: #9b9b9b;
    letter-spacing: .26px;
    padding-top: 20px;
}
.inp .go_login span{
    color: #84cc39;
    cursor: pointer;
}
</style>

Front-end registered routing:

import Register from "../components/Register"

// Configure Routing List
export default new Router({
  mode:"history",
  routes:[
    // Routing List
	...
    {
      path: "/user/register",
      name:"Register",
      component:Register,
    }
  ]
})

Modify the connection at the head of the home page:

# Header.vue
<span class="header-register"><router-link to="/register">register</router-link></span>
#Login.vue
<p class="go_login" >No account <router-link to="/register">Immediate registration</router-link></p>

Implementation of Registration Function

View code:

from rest_framework.generics import CreateAPIView
from .models import User
from .seriazliers import UserModelSerializer
class UserAPIView(CreateAPIView):
    queryset = User.objects.filter(is_active=True).all()
    serializer_class = UserModelSerializer

Serializer, user sub-application to create sreializers.py file, code:

from rest_framework import serializers
from .models import User
class UserModelSerializer(serializers.ModelSerializer):
    """User Registered Serializer"""
    # Field declaration
    sms_code = serializers.CharField(write_only=True, max_length=6, help_text="Short Message Verification Code")
    token = serializers.CharField(max_length=1024, read_only=True, help_text="jwt Of token Character string")

    # Model information
    class Meta:
        model = User
        fields = ["id", "mobile", "password", "sms_code", "token"]
        extra_kwargs = {
            "id":{
              "read_only":True,
            },
            "mobile":{
                "max_length": 15,
                "required": True
            },
            "password":{
                "write_only": True,
                "max_length": 128,
                "required": True
            }
        }

    # Validation data


    # Save information
    def create(self, validated_data):
        """Adding users"""
        # Delete fields that do not exist in the database
        del validated_data["sms_code"]

        # Save user information and set default values for some fields
        validated_data["username"] = validated_data["mobile"]

        # Call the create of the current model serializer parent class
        user = super().create(validated_data)

        # Generate the token value of jwt to record login status
        from rest_framework_jwt.settings import api_settings
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)

        # Finally, token is returned to the client as a field of the user model
        user.token = jwt_encode_handler(payload)

        return user

Routing address

from django.urls import path, re_path
from . import views
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
    path(r'authorizations/', obtain_jwt_token, name='authorizations'),
    path(r'captcha/', views.CaptchaAPIView.as_view()),
    path(r'', views.UserAPIView.as_view() ),
]

Client submits registration information

Next, we need to re-register the page to provide the function of sending SMS validation, so the page is adjusted, code:

<template>
	<div class="box">
		<img src="/static/image/Loginbg.3377d0c.jpg" alt="">
		<div class="register">
			<div class="register_box">
        <div class="register-title">Registered Lufei School Town</div>
				<div class="inp">
					<input v-model="mobile" type="text" placeholder="Phone number" class="user">
          <input v-model="password" type="password" placeholder="Input password" class="user">
					<div class="sms_code">
            <input v-model="sms" type="text" maxlength="6" placeholder="Input Verification Code" class="user">
            <span class="code_text">Click Send SMS</span>
          </div>
          <div id="geetest"></div>
					<button class="register_btn" @click="registerHander">register</button>
					<p class="go_login" >Existing accounts <router-link to="/user/login">Direct login</router-link></p>
				</div>
			</div>
		</div>
	</div>
</template>

<script>
export default {
  name: 'Register',
  data(){
    return {
        sms:"",
        mobile:"",
        password:"",
        validateResult:false,
    }
  },
  created(){
  },
  methods:{
      registerHander(){
          // User registration
          // 1. Accept validation data
          if( !/1[3-9]\d{9}/.test(this.mobile) ){
              this.$message("Sorry, there's a wrong cell phone number!");
          }
          if( this.password.length < 6 || this.password.length > 16 ){
              this.$message("Sorry, password must be kept at 6-16 Between Bit Characters");
          }

          if( this.sms.length != 6 ){
              this.$message("Sorry, the SMS authentication code is wrong!");
          }

          // 2. Send ajax
          this.$axios.post(`${this.$settings.Host}/user/`,{
              mobile:this.mobile,
              password:this.password,
              sms_code:this.sms
          }).then(response=>{
              // Save login status
              sessionStorage.user_id = response.data.id;
              sessionStorage.user_name = response.data.mobile;
              sessionStorage.user_token = response.data.token;
              let self = this;
              this.$alert("Welcome to register Lufei School Town!","login was successful",{
                  callback(){
                      self.$router.push("/");
                  }
              })
          })
      }
  },

};
</script>

<style scoped>
.box{
	width: 100%;
  height: 100%;
	position: relative;
  overflow: hidden;
}
.box img{
	width: 100%;
  min-height: 100%;
}
.box .register {
	position: absolute;
	width: 500px;
	height: 400px;
	left: 0;
  margin: auto;
  right: 0;
  bottom: 0;
  top: -338px;
}
.register .register-title{
    width: 100%;
    font-size: 24px;
    text-align: center;
    padding-top: 30px;
    padding-bottom: 30px;
    color: #4a4a4a;
    letter-spacing: .39px;
}
.register-title img{
    width: 190px;
    height: auto;
}
.register-title p{
    font-size: 18px;
    color: #fff;
    letter-spacing: .29px;
    padding-top: 10px;
    padding-bottom: 50px;
}
.register_box{
    width: 400px;
    height: auto;
    background: #fff;
    box-shadow: 0 2px 4px 0 rgba(0,0,0,.5);
    border-radius: 4px;
    margin: 0 auto;
    padding-bottom: 40px;
}
.register_box .title{
	font-size: 20px;
	color: #9b9b9b;
	letter-spacing: .32px;
	border-bottom: 1px solid #e6e6e6;
	 display: flex;
    	justify-content: space-around;
    	padding: 50px 60px 0 60px;
    	margin-bottom: 20px;
    	cursor: pointer;
}
.register_box .title span:nth-of-type(1){
	color: #4a4a4a;
    	border-bottom: 2px solid #84cc39;
}

.inp{
	width: 350px;
	margin: 0 auto;
}
.inp input{
    outline: 0;
    width: 100%;
    height: 45px;
    border-radius: 4px;
    border: 1px solid #d9d9d9;
    text-indent: 20px;
    font-size: 14px;
    background: #fff !important;
}
.inp input.user{
    margin-bottom: 16px;
}
.inp .rember{
     display: flex;
    justify-content: space-between;
    align-items: center;
    position: relative;
    margin-top: 10px;
}
.inp .rember p:first-of-type{
    font-size: 12px;
    color: #4a4a4a;
    letter-spacing: .19px;
    margin-left: 22px;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-align: center;
    align-items: center;
    /*position: relative;*/
}
.inp .rember p:nth-of-type(2){
    font-size: 14px;
    color: #9b9b9b;
    letter-spacing: .19px;
    cursor: pointer;
}

.inp .rember input{
    outline: 0;
    width: 30px;
    height: 45px;
    border-radius: 4px;
    border: 1px solid #d9d9d9;
    text-indent: 20px;
    font-size: 14px;
    background: #fff !important;
}

.inp .rember p span{
    display: inline-block;
  font-size: 12px;
  width: 100px;
  /*position: absolute;*/
/*left: 20px;*/

}
#geetest{
	margin-top: 20px;
}
.register_btn{
     width: 100%;
    height: 45px;
    background: #84cc39;
    border-radius: 5px;
    font-size: 16px;
    color: #fff;
    letter-spacing: .26px;
    margin-top: 30px;
}
.inp .go_login{
    text-align: center;
    font-size: 14px;
    color: #9b9b9b;
    letter-spacing: .26px;
    padding-top: 20px;
}
.inp .go_login span{
    color: #84cc39;
    cursor: pointer;
}
.sms_code{
    position: relative;
}
.code_text{
    position: absolute;
    right: 14px;
    top: 13px;
    border-left: 1px solid orange;
    padding-left: 14px;
    cursor: pointer;
    background-color: #fff;
}
</style>

Next, we complete the configuration of redis database in the registration process.

If you need to operate redis directly through code in django, you need to install django-redis.

This module is based on pyredis. Pyredis is the most commonly used module to operate redis in python.

It will provide all commands of redis as function names for developers to use, and the parameters of each command function are the command parameters in the terminal.

pip install django-redis

Add a code to the settings/dev.py configuration:

# Setting up redis cache
CACHES = {
    # Default cache
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        # When the project goes online, you need to adjust the path here.
        "LOCATION": "redis://127.0.0.1:6379/0",

        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
    # session storage for xadmin or admin
    "session": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
    # Provide Storage Short Message Verification Code
    "sms_code":{
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/2",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}

# When setting xadmin user login, login information session is saved to redis
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "session"

For the use of django-redis, the documentation is available at http://django-redis-chs.readthedocs.io/zh_CN/latest./

django-redis provides a method to get_redis_connection. The configuration name of redis can be passed by calling get_redis_connection method to get the connection object of redis. The redis command can be executed through the connection object of redis.

https://redis-py.readthedocs.io/en/latest/

Use examples:

from django_redis import get_redis_connection
// link redis data base
redis_conn = get_redis_connection("default")

Sending SMS Using Cloud Communication

Common text messaging platforms: Aliyun, Tencent, Netease, Sina, Baidu, Yung Lianyun, Rose Cat

Get information on the login platform:

ACCOUNT SID: xxx
AUTH TOKEN : xxx
AppID(default): xxx
Rest URL(production):  app.cloopen.com:8883         [Use Real Short Message Sending Server for Project Online]
Rest URL(Development):  sandboxapp.cloopen.com:8883  [Sandbox Short Message Sending Server for Project Development]

Find sdkdemo for download

In the development process, in order to save the cost of sending short messages, you can add your own or colleague's mobile phone to the test number.

Back-end Generation of Short Message Verification Code

settings/dev.py configuration

# Configuration of Short Message Verification Code
SMS_ACCOUNTSID = "8aa*************************d228e"
SMS_ACCOUNTTOKEN = "62fc*************************03de"
SMS_APPID = "8aaf*************************f782295"
SMS_SERVERIP = "sandboxapp.cloopen.com"
SMS_EXPIRE_TIME = 300
SMS_INTERVAL_TIME = 60
SMS_TEMPLATE_ID = 1

users/views.py view file

from rest_framework.views import APIView
from luffyapi.libs.geetest import GeetestLib
from rest_framework.response import Response
from django.conf import settings

class CaptchaAPIView(APIView):
    """Extreme Verification Code"""
    def get(self,request):
        """Pipeline Number and State for Generating Verification Codes"""
        gt = GeetestLib(settings.PC_GEETEST_ID, settings.PC_GEETEST_KEY)
        status = gt.pre_process(settings.PC_GEETEST_USER_ID)
        response_str = gt.get_response_str()
        return Response(response_str)

    def post(self,request):
        """Secondary verification"""
        gt = GeetestLib(settings.PC_GEETEST_ID, settings.PC_GEETEST_KEY)
        challenge = request.data.get(gt.FN_CHALLENGE, '')
        validate = request.data.get(gt.FN_VALIDATE, '')
        seccode = request.data.get(gt.FN_SECCODE, '')

        result = gt.success_validate(challenge, validate, seccode, settings.PC_GEETEST_USER_ID)
        if not result:
            result = gt.failback_validate(challenge, validate, seccode)

        return Response({"status": result})


from rest_framework.generics import CreateAPIView
from .models import User
from .seriazliers import UserModelSerializer
class UserAPIView(CreateAPIView):
    queryset = User.objects.filter(is_active=True).all()
    serializer_class = UserModelSerializer
   


"""
/users/sms/13112345678
"""
from rest_framework import status
import random
from django_redis import get_redis_connection
from luffyapi.libs.yuntongxun.sms import CCP
class SMSCodeAPIView(APIView):
    def get(self,request,mobile):
        """Send short messages"""
        # 1. Verify that the mobile phone number has been registered.
        try:
            User.objects.get(mobile=mobile)
            return Response({"message": "Sorry, the mobile phone number has been registered at present."}, status=status.HTTP_400_BAD_REQUEST)
        except User.DoesNotExist:
            # If the mobile phone number does not exist in the database, it means no registration and no processing.
            pass

        # 2. Verify the sending interval of SMS [60s]
        # 2.1 Link redis
        redis = get_redis_connection("sms_code")

        # Use get to get the value of the specified key and return None if not
        interval = redis.get("exp_%s" % mobile)
        if interval:
            return Response({"message": "Sorry, the short message interval!"}, status=status.HTTP_403_FORBIDDEN)

        # 3.1 Generating Random Short Message Verification Code
        sms_code = "%06d" % random.randint(0,999999)

        # 3.2 Save the validation code sent to redis [mobile phone number, short message validation code, short message sending interval, short message validity]
        """
        //Character string
            setex sms_Mobile phone number 300 short message verification code
            setex exp_Mobile phone number 60  _
        """
        redis.setex("sms_%s" % mobile, settings.SMS_EXPIRE_TIME, sms_code)
        redis.setex("exp_%s" % mobile, settings.SMS_INTERVAL_TIME, "_")

        # 3.3 Call sdk to send short messages
        ccp = CCP()
        result = ccp.send_template_sms(mobile, [sms_code, settings.SMS_EXPIRE_TIME//60 ], settings.SMS_TEIMPLATE_ID)

        # 4. Return the result of sending SMS
        if result == -1:
            return Response({"message":"Failed to send SMS!"},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        else:
            return Response({"message":"Successful text messaging!"},status=status.HTTP_200_OK)

Backend saves user registration information

Create serializer objects [not involving mobile phone validation code functionality for the time being]

from rest_framework import serializers
from .models import User
import re
class UserModelSerializer(serializers.ModelSerializer):
    """User Information Serializer"""
    sms_code = serializers.CharField(label='Mobile phone verification code', required=True, allow_null=False, allow_blank=False, write_only=True)
    password2 = serializers.CharField(label='Confirm password', required=True, allow_null=False, allow_blank=False, write_only=True)

    class Meta:
        model=User
        fields = ('sms_code', 'mobile', 'password','password2')
        extra_kwargs={
            "password":{
                "write_only":True
            }
        }

    def validate_mobile(self, value):
        """Verification of mobile phone number"""
        if not re.match(r'^1[345789]\d{9}$', value):
            raise serializers.ValidationError('Incorrect format of mobile phone number')

        # Verify that the phone number has been registered
        # try:
        #     user = User.objects.get(mobile=value)
        # except:
        #     user = None
        #
        # if user:
        #     Raise serializers. Validation Error ('The current phone number has been registered')

        # Code above to verify the existence of mobile phone number [Optimized Edition]
        try:
            User.objects.get(mobile=value)
            # If the user information is obtained, the following code will not be executed. If the user information is not obtained, the mobile phone number has not been registered and can be directly pass ed.
            raise serializers.ValidationError('Current mobile phone number has been registered')
        except:
            pass

        return value

    def validate(self,data):
        # Verify password
        password = data.get("password")
        password2 = data.get("password2")
        if len(password)<6:
            raise serializers.ValidationError('Passwords are too short and unsafe~')

        if password !=password2:
            raise serializers.ValidationError('Password and confirmation must be consistent~')

        return data

    def create(self, validated_data):
        # Delete fields that do not need to be saved to the database
        del validated_data['password2']
        del validated_data['sms_code']
        
        # Because the default user name is unique in the database, we use the user's mobile phone number as the user name.
        validated_data["username"] = validated_data["mobile"]
        
        # Continue calling the built-in add data function of ModelSerializer
        user = super().create(validated_data)

        # Encryption for passwords
        user.set_password(user.password)
        # Modifying passwords and so on are used to update passwords, so they need to be saved.
        user.save()

        return user

View code:
users/views.py

# users/views.py
from rest_framework.generics import CreateAPIView
from .models import User
from .serializers import UserModelSerializer
class UserAPIView(CreateAPIView):
    """user management"""
    queryset = User.objects.all()
    serializer_class = UserModelSerializer

Setting up routing

urls.py

# Subapplication routing urls.py
urlpatterns=[
	...
    path(r"user", views.UserAPIView.as_view()),
]

Client sends registration information and SMS

<template>
	<div class="box">
		<img src="https://www.luffycity.com/static/img/Loginbg.3377d0c.jpg" alt="">
		<div class="register">
			<div class="register_box">
        <div class="register-title">Registered Lufei School Town</div>
				<div class="inp">
          <!--<el-select v-model="region">-->
            <!--<el-option v-for="item in region_list" :label="item.nation_name+'('+item.nation_code+')'" :value="item.nation_code"></el-option>-->
          <!--</el-select>-->
					<input v-model = "mobile" type="text" placeholder="Phone number" class="user">
					<input v-model = "password" type="password" placeholder="Password" class="user">
					<input v-model = "password2" type="password" placeholder="Confirm password" class="user">
          <div id="geetest"></div>
					<div class="sms">
            <input v-model="sms_code" maxlength="16" type="text" placeholder="Input Verification Code" class="user">
            <span class="get_sms" @click="send_sms">{{get_sms_text}}</span>
          </div>
					<button class="register_btn" @click="registerHander">register</button>
					<p class="go_login" >Existing accounts <router-link to="/login">Direct login</router-link></p>
				</div>
			</div>
		</div>
	</div>
</template>

<script>
export default {
  name: 'Register',
  data(){
    return {
        region:"+86",
        sms_code:"",
        password:"",
        password2:"",
        mobile:"",
        validateResult:false,
        get_sms_text:"Get the authentication code",
    }
  },
  created(){
    // Set the area number when the page is initialized
    // this.region_list = this.$nation;

    // Display Picture Verification Code
    this.$axios.get("http://127.0.0.1:8000/users/verify").then(response=>{
          // Successful request
          let data = response.data;
          // Using initGeetest interface
          // Parametric 1: Configuration parameters
          // Parametric 2: Callback, the first parameter validation code object of the callback, which can then be used for events such as appendTo
          console.log(response.data);
          data = JSON.parse(data);
          initGeetest({
              gt: data.gt,
              challenge: data.challenge,
              width: "350px",
              product: "embed", // Product form, including: float, embed ded, popup. Note that only valid for PC version validation code
              offline: !data.success // Represents that the user background checks whether the polar test server is down or not, and generally does not need attention.
              // For more configuration parameters, see http://www.geetest.com/install/sections/idx-client-sdk.html#config
          }, this.handlerPopup);
    }).catch(error=>{
      console.log(error)
    })

  },
  methods:{
    send_sms(){
      let reg = /1[1-9]{2}\d{8}/;
      if( !reg.test(this.mobile) ){
        return false;
      }

      // If get_sms_text is not text, but a number, it means that the current mobile phone number is still within 60 seconds of sending short messages.
      if(this.get_sms_text != "Get the authentication code"){
        return false;
      }

      // Send short messages
      let _this = this;
      this.$axios.get("http://127.0.0.1:8000/users/sms?mobile="+this.mobile).then(response=>{
        console.log(response);
        // Display text countdown after sending SMS
        let time = 60;
        let timer = setInterval(()=>{
          --time;
          if(time <=1){
            // If the countdown is 0, turn off the current timer
             _this.get_sms_text = "Get the authentication code";
            clearInterval(timer);
          }else{
              _this.get_sms_text = time;
          }
        },1000)
      }).catch(error=>{
        console.log(error);
      })

    },
    registerHander(){
      // Registration Information Submission
      // Determine whether the user has passed the validation code before submitting the data
      if(!this.validateResult){
          alert("Error in Verification Code Validation");
          return false;
      }
      this.$axios.post("http://127.0.0.1:8000/users/user",{
          "mobile":this.mobile,
          "password":this.password,
          "password2":this.password2,
          "sms_code":this.sms_code,
        },{
          responseType:"json",
        }).
          then(response=>{
            // Successful request, save login status
            localStorage.removeItem("token");
            let data = response.data;
            sessionStorage.token = data.token;
            sessionStorage.id = data.id;
            sessionStorage.username = data.mobile;
            // After successful registration, the default indication is that you have logged in and jumped to the user center page.
            // this.$router.push("/user");
            alert("login was successful!");
        }).catch(error=>{
          console.log(error);
        })
      },
    handlerPopup(captchaObj){
        // Callback of Verification Code Successfully
        let _this = this;
        captchaObj.onSuccess(function () {
            var validate = captchaObj.getValidate();
            _this.$axios.post("http://127.0.0.1:8000/users/verify",{
                    geetest_challenge: validate.geetest_challenge,
                    geetest_validate: validate.geetest_validate,
                    geetest_seccode: validate.geetest_seccode
                },{
                  responseType:"json",
            }).then(response=>{
              // Successful request
              console.log(response.data);
              if(response.data.status == "success") {
                  _this.validateResult = true;  // Get the validation results
              }
            }).catch(error=>{
              // request was aborted
              console.log(error)
            })
        });
        // Add the validation code to the element with id captcha
        captchaObj.appendTo("#geetest");
      }
  },

};
</script>

<style scoped>
.box{
	width: 100%;
  height: 100%;
	position: relative;
  overflow: hidden;
}
.el-select{
  width:100%;
  margin-bottom: 15px;
}
.box img{
	width: 100%;
  min-height: 100%;
}
.box .register {
	position: absolute;
	width: 500px;
	height: 400px;
	top: 0;
	left: 0;
  margin: auto;
  right: 0;
  bottom: 0;
  top: -338px;
}
.register .register-title{
    width: 100%;
    font-size: 24px;
    text-align: center;
    padding-top: 30px;
    padding-bottom: 30px;
    color: #4a4a4a;
    letter-spacing: .39px;
}
.register-title img{
    width: 190px;
    height: auto;
}
.register-title p{
    font-family: PingFangSC-Regular;
    font-size: 18px;
    color: #fff;
    letter-spacing: .29px;
    padding-top: 10px;
    padding-bottom: 50px;
}
.sms{
  margin-top: 15px;
  position: relative;
}
.sms .get_sms{
  position: absolute;
  right: 15px;
  top: 14px;
  font-size: 14px;
  color: #ffc210;
  cursor: pointer;
  border-left: 1px solid #979797;
  padding-left: 20px;
}

.register_box{
    width: 400px;
    height: auto;
    background: #fff;
    box-shadow: 0 2px 4px 0 rgba(0,0,0,.5);
    border-radius: 4px;
    margin: 0 auto;
    padding-bottom: 40px;
}
.register_box .title{
	font-size: 20px;
	color: #9b9b9b;
	letter-spacing: .32px;
	border-bottom: 1px solid #e6e6e6;
	 display: flex;
    	justify-content: space-around;
    	padding: 50px 60px 0 60px;
    	margin-bottom: 20px;
    	cursor: pointer;
}
.register_box .title span:nth-of-type(1){
	color: #4a4a4a;
    	border-bottom: 2px solid #84cc39;
}

.inp{
	width: 350px;
	margin: 0 auto;
}
.inp input{
    border: 0;
    outline: 0;
    width: 100%;
    height: 45px;
    border-radius: 4px;
    border: 1px solid #d9d9d9;
    text-indent: 20px;
    font-size: 14px;
    background: #fff !important;
}
.inp input.user{
    margin-bottom: 16px;
}
.inp .rember{
     display: flex;
    justify-content: space-between;
    align-items: center;
    position: relative;
    margin-top: 10px;
}
.inp .rember p:first-of-type{
    font-size: 12px;
    color: #4a4a4a;
    letter-spacing: .19px;
    margin-left: 22px;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-align: center;
    align-items: center;
    /*position: relative;*/
}
.inp .rember p:nth-of-type(2){
    font-size: 14px;
    color: #9b9b9b;
    letter-spacing: .19px;
    cursor: pointer;
}

.inp .rember input{
    outline: 0;
    width: 30px;
    height: 45px;
    border-radius: 4px;
    border: 1px solid #d9d9d9;
    text-indent: 20px;
    font-size: 14px;
    background: #fff !important;
}

.inp .rember p span{
    display: inline-block;
  font-size: 12px;
  width: 100px;
  /*position: absolute;*/
/*left: 20px;*/

}
#geetest{
	margin-top: 20px;
}
.register_btn{
     width: 100%;
    height: 45px;
    background: #84cc39;
    border-radius: 5px;
    font-size: 16px;
    color: #fff;
    letter-spacing: .26px;
    margin-top: 30px;
}
.inp .go_login{
    text-align: center;
    font-size: 14px;
    color: #9b9b9b;
    letter-spacing: .26px;
    padding-top: 20px;
}
.inp .go_login span{
    color: #84cc39;
    cursor: pointer;
}
</style>


Be careful:
If HTTP 403 error occurs during sending validation code test, clear the local cookie and try again.

Posted by ncracraf on Wed, 14 Aug 2019 05:09:24 -0700