vue_drf 문자 인증 코드 구현

수요
1,수요
우리 가 사이트 개발 을 할 때 로그 인 페이지 의 많은 상황 에서 핸드폰 번호 로 문자 인증 코드 를 받 은 후에 로그 인 을 실현 할 수 있다.그러면 우 리 는 오늘 이 기능 을 하 겠 다.

의사 코드:
로그 인 페이지 에 들 어가 문자 로 로그 인
핸드폰 번 호 를 입력 하고 인증 코드 를 가 져 오 려 면 누 르 십시오.백 엔 드 는 redis 에 인증 코드 를 저장 합 니 다.
사용 자 는 핸드폰 으로 받 은 인증 번 호 를 입력 하고 로그 인 을 클릭 하면 핸드폰 번호 와 인증 번 호 를 백 엔 드 로 보 내 고 검증 을 한다.
문 자 를 보 내 고 사용자 에 게 문 자 를 받 게 하려 면 저 희 는 용 련 클 라 우 드 의 인 터 페 이 스 를 통 해 계 정 을 등록 합 니 다.

사용 시 필요 한 인자:

sdk 다운로드
  1.。。。。。。。

  2.。。。。。。

  3.。。。。。。。

다운로드 완료 후 압축 해제.우리 drf 프로젝트 의 apps 에 libs 를 넣 습 니 다.
2.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)
3.코드 구현
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('      ')
        }
      },
vuedrf 문자 인증 코드 를 실현 하 는 글 은 여기까지 입 니 다.vuedrf 문자 인증 코드 내용 은 저희 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!

좋은 웹페이지 즐겨찾기