vue_drf は SMS 認証コードを実装します

vue_drf は SMS 認証コードを実装します

1. 需要

1. 需要

ウェブサイトを開発している場合、多くの場合、ログインページでは携帯電話番号を使用してテキストメッセージの検証コードを受信して​​からログインすることができます。今日はこの機能を実行してみましょう。

疑似コード:

ログイン ページに入り、「SMS ログイン」をクリックし、携帯電話番号を入力して、「確認コードの取得」をクリックすると、バックエンドは確認コードを Redis に保存します。ユーザーは携帯電話で受信した確認コードを入力し、「ログイン」をクリックすると、携帯電話番号と確認コードが確認のためにバックエンドに送信されます。

テキスト メッセージを送信し、ユーザーがテキスト メッセージを受信できるようにするには、RongCloud インターフェイスを使用してアカウントを登録します。

使用に必要なパラメータ:

SDKをダウンロード

1. 。 。 。 。 。 。

2. 。 。 。 。 。

3. 。 。 。 。 。 。

ダウンロード後、解凍してください。 drfプロジェクトのアプリのライブラリに配置する

2. SDKパラメータ設定

1. ディレクトリ構造

2. sms.pyファイルを設定する

# -*- コーディング:utf-8 -*-

.CCPRestSDKからRESTをインポート

# 注: クラウド コミュニケーション Web サイトにログインすると、「コンソール アプリケーション」で開発者のメイン アカウントの ACCOUNT SID を確認できます。
_accountSid = 'xxxxxxxxxxxx'
# 8a216da863f8e6c20164139687e80c1b
# 説明: メインアカウントトークンは、クラウド通信ウェブサイトにログインした後、コンソールアプリケーションで開発者のメインアカウントAUTH TOKENを確認できます。
_accountToken = 'xxxxxxxxxxxxxxx'
6dd01b2b60104b3dbc88b2b74158bac6 翻訳:
# 管理コンソールのホームページにあるAPPID、または自分で作成したアプリケーションのAPPIDを使用してください
_アプリID = '8aaf0708697b6beb01699f3c645f1766'
# 8a216da863f8e6c20164139688400c21
# 注: リクエストアドレス。本番環境は app.cloopen.com として構成されています
_serverIP = 'sandboxapp.cloopen.com'

# 説明: リクエストポート、本番環境は 8883 です
_serverPort = "8883"

# 注意: REST API のバージョン番号は変更されません_softVersion = '2013-12-26'

#次の内容は変更する必要はありません class CCP(object):
    「SMS メッセージを送信するための補助クラス」

    def __new__(cls, *args, **kwargs):
        # クラス属性 _instance があるかどうかを確認します。_instance はクラス CCP の唯一のオブジェクトです。つまり、そうでない場合はシングルトンです。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)
        cls._instance を返す

    def send_template_sms(自分、送信先、データ、temp_id):
        「テンプレート SMS を送信」
        # @param 携帯電話番号 # @param datas コンテンツデータの形式は配列です。例: {'12','34'}、置換が不要な場合は '' を入力してください
        # @param temp_id テンプレートID
        結果 = self.rest.sendTemplateSMS(宛先、データ、temp_id)
        # クラウド通信がSMSを正常に送信すると、返される辞書データ結果のstatuCodeフィールドの値は「000000」になります。
        result.get("statusCode") == "000000"の場合:
            # 0 を返すと、SMS メッセージが正常に送信されたことを意味します。0 を返します。
        それ以外:
            # -1 を返すと送信失敗を意味します -1 を返します


__name__ == '__main__' の場合:
    ccp = CCP()
    # 注意: テストのSMSテンプレート番号は1です
    ccp.send_template_sms('15914397060', ['1234', 5], 1)

3. コードの実装

1. バックエンドコード

views.py、これは検証コード要求を取得する処理です。つまり、バックエンドはランダムコードを生成し、それを携帯電話ユーザーに送信し、ランダムコードをredisに保存し、検証コード送信成功信号をフロントエンドに返します。

.models から User をインポート
rest_framework からインポートステータス
lufei_drf.libs.yuntongxun.sms から CCP をインポート
django_redis から get_redis_connection をインポートします
クラス SMSCodeAPIView(APIView):
    def get(self, request):
        # 1. クエリ文字列を通じて電話番号を取得します。phone = request.query_params.get("phone")
        ty = request.query_params.get('type')
        # 2. ty=='register'の場合、SMSを送信する前に確認コードで携帯電話番号を確認します。
            試す:
                User.objects.get(電話=電話)
                レスポンスを返します({"message": "現在の電話番号は登録されています"}, status=status.HTTP_400_BAD_REQUEST)
            を除外する:
                合格
        redis = get_redis_connection("sms_code")
        redis.get("times_%s" % 電話の場合):
            return Response({"message": "現在の電話番号が 1 分以内にテキストメッセージを送信しました"}, status=status.HTTP_400_BAD_REQUEST)

        # 3. 携帯電話番号を使用してテキストメッセージの確認コードを送信します# テキストメッセージの確認コードを生成します sms_code = "%04d" % random.randint(0, 9999)
        ccp = CCP()
        結果 = ccp.send_template_sms(phone,[sms_code,"5 minutes"],1)

        結果 == 0 の場合:
            #SMS を正常に送信し、SMS 検証コードを redis データベースに保存します#パイプライン操作を開きます pl = redis.pipeline()
            pl.multi() # 次に、パイプラインで複数のコマンドが実行されます # setex(変数名、有効期間 [秒]、値)
            SMS_EXPIRE_TIME = 5 * 60 # SMS 検証コードの有効期間 SMS_TIMES = 60 # SMS 送信間隔 # 元の即時実行コマンドをパイプラインに挿入します pl.setex("sms_%s" % phone, SMS_EXPIRE_TIME, sms_code)
            pl.setex("times_%s" % 電話、SMS_TIMES、1)

            # パイプライン内のコマンドの実行を統一する pl.execute()

        # 4. クライアントへの応答データは Response({"message":result},status=status.HTTP_200_OK) を返します。

urls.py

django.urls インポートパスから
# ログインビューは jwt によって内部的に実装されています from rest_framework_jwt.views import obtained_jwt_token
.viewsからSMSCodeAPIViewをインポートし、

urlパターン=[
    パス(r"login/", get_jwt_token ),
    パス('sms/'、SMSCodeAPIView.as_view())、
]

utils.py は、ユーザーが携帯電話の確認コードを送信した後に、携帯電話番号と確認コードをチェックします。すべての判断が正しければ、トークン、ユーザー情報などを含むオブジェクトが返されます。

django.contrib.auth.backends から ModelBackend をインポートします
django_redis から get_redis_connection をインポートします


def jwt_response_payload_handler(トークン、ユーザー=なし、リクエスト=なし):
    「」
    カスタム jwt 認証が正常にデータを返します: トークンによって返された jwt
    :user 現在ログインしているユーザーの情報 [オブジェクト]
    :request クライアントによって現在送信されているデータ"""
    戻る {
        'トークン': トークン、
        'id': ユーザーID、
        'ユーザー名': user.ユーザー名,
    }

#多機能ログインインポート再を実現
from .models import User#ユーザー名または電話番号がすでにユーザーであるかどうかを確認します def get_user_by_account(account):
    「」
    アカウントに基づいてユーザー オブジェクトを取得します:param account: アカウント (ユーザー名または電話番号) を返します:return: ユーザー オブジェクトまたは None
    「」
    試す:
        re.match('^1[3-9]\d{9}$', アカウント):
            # アカウントは携帯電話番号です user = User.objects.get(phone=account)
        それ以外:
            # アカウントはユーザー名です user = User.objects.get(username=account)
    User.DoesNotExistを除く:
        なしを返す
    それ以外:
        ユーザーを返す
#ユーザーが送信した SMS メッセージが redis に保存した情報と一致しているかどうかを確認します。def sms_code_verify(phone, sms_code):
    redis = get_redis_connection("sms_code")
    値=redis.get('sms_%s'%phone).decode()
    値==sms_codeの場合:
        Trueを返す
    Falseを返す

クラスUsernameMobileAuthBackend(ModelBackend):
    「」
    ユーザー名または電話番号認証をカスタマイズする"""
    def authenticate(self, request, ユーザー名=None, パスワード=None, **kwargs):
        user = get_user_by_account(username) #パスワードの長さが4の場合、携帯電話番号とSMS認証コードによるログインであると判断します。if len(password)==4かつuserがNoneでなく、sms_code_verify(username,password):
            ユーザーを返す
        elif ユーザーが None ではなく、user.check_password(password):
            ユーザーを返す
        それ以外:
            なしを返す

2. フロントエンドコード

ログインコンポーネント

<テンプレート>
  <div id="ログイン">
    <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 カーソル">
          <span @click="num=1" :class="num==1 ? 'show' :''">パスワードログイン</span>
              <span @click="num=2" :class="num==2 ? 'show' :''">SMS ログイン</span>
        </div>
        <input v-model="username" type="text" class="ss" placeholder="ユーザー名/携帯電話番号">
        <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="remember">
            <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="message" v-show="num==2">
        <div class="title2 カーソル">
          <span @click="num=1" :class="num==1 ? 'show' :''">パスワードログイン</span>
              <span @click="num=2" :class="num==2 ? 'show' :''">SMS ログイン</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>
</テンプレート>

<スクリプト>
  エクスポートデフォルト{
    名前:'ログイン',
    データ:関数() {
      戻る {
        番号:1,
        ユーザー名:''、
        パスワード:''、
        覚えておいてください:''
        状態:''、
        コンテンツ:'認証コードを取得',
        電話:''、
        SMSコード:''、
      }
    },
    方法:{
      //携帯電話番号とSMS認証コードログイン sms_login:function(){
        _this=this とします。
        this.$axios.post('http://127.0.0.1:8000/user/login/',{
            'ユーザー名':_this.phone,
            'パスワード':_this.sms_code,
          },{レスポンスタイプ:'json'})
          .then(関数 (res) {
            セッションストレージトークン = res.data.token;
             _this.$router.go(-1);
          }).catch(関数(エラー) {
          コンソール.log(エラー.応答)
        });
      },
      //SMS認証コードを取得するget_sms_code:function(){
        reg = /1[3-9]{2}\d{8}/とします。
        if(reg.test(this.phone)){
          if(this.content == "認証コードを取得"){
            60 文字以内
            _this=this とします。
            tt = setInterval(関数() {
              _this.content>=1の場合{
                _this.content--
              }
              それ以外 {
                _this.content='認証コードを取得する';
                クリア間隔(tt)
              }
            },1000);
            this.$axios.get('http://127.0.0.1:8000/user/sms?type=login&phone='+this.phone)
              .then(関数 (res) {
                res.data.message==0の場合{
                  alert('認証コードが正常に送信されました')
                }
              }).catch(関数(エラー) {
                コンソール.log(エラー.応答)
              })
          }
        }それ以外 {
          アラート('携帯電話番号が間違っています')
        }
      },
      //ユーザー名とパスワード login1:function () {
        if (this.status==1){
          _this=this とします。
          this.$axios.post('http://127.0.0.1:8000/user/login/',{
            'ユーザー名':_this.ユーザー名,
            'パスワード':_this.password,
          },{レスポンスタイプ:'json'})
          .then(関数 (res) {
            (res.status==200)の場合{
              if (_this.remember){
                sessionStorage.removeItem('トークン');
                ローカルストレージトークン = res.data.token;
              }
              それ以外 {
                localStorage.removeItem('トークン');
                セッションストレージトークン=res.data.token
              }
              _this.$router.go(-1);
            }
            それ以外 {
              アラート('ユーザー名またはパスワードが正しくありません')
            }
          })
          .catch(関数 (エラー) {
            アラート(error.response.data.non_field_errors[0]);
            コンソールにログ出力します。
          });
        }
        それ以外 {
          アラート('認証コードエラー')
        }
      },
      ハンドラポップアップ:関数 (captchaObj) {
        _this=this とします。
        captchaObj.onSuccess(関数() {
           var 検証 = captchaObj.getValidate();
           _this.$axios.post("http://127.0.0.1:8000/user/yzm/",{
                    geetest_challenge: 検証.geetest_challenge、
                    geetest_validate: 検証.geetest_validate、
                    geetest_seccode: 検証.geetest_seccode、
                },{
                  レスポンスタイプ:"json",
            }).then(関数(res) {
              _this.status=res.data.status
           }).catch(関数(エラー) {
             コンソール.log(エラー)
           })
        });
        captchaObj.appendTo("#captcha");
      }
    },
    作成された:関数() {
      _this=this とします。
      this.$axios.get("http://127.0.0.1:8000/user/yzm")
        .then(関数 (res) {
          データをJSON.parse(res.data)とします。
          initGeetest({
                幅:'350px',
                gt: データ.gt、
                チャレンジ: データチャレンジ、
                製品:「ポップアップ」、
                オフライン: !data.success
            }, _this.handlerPopup);
        }).catch(関数(エラー) {
          コンソール.log(エラー)
      })
    }
    
  }
</スクリプト>

<スタイルスコープ>
#ログイン{
  背景: url('../../assets/Login.jpg');
  背景サイズ: 100% 100%;
  高さ: 100%;
  位置: 固定;
  幅: 100%;
}
。箱{
  幅: 500ピクセル;
  高さ: 600px;
  マージン: 0 自動;
  上マージン: 200px;
  テキスト配置: 中央;
}
.box 画像{
  幅: 190ピクセル;
  高さ: 自動;
}
.box p{
  マージン: 0;
}
。サイン{
  フォントサイズ: 18px;
  色: #fff;
  文字間隔: .29px;
  パディング上部: 10px;
  パディング下部: 50px;
}
。合格{
  幅: 400ピクセル;
  高さ: 460ピクセル;
  マージン: 0 自動;
  背景色: 白;
  境界線の半径: 4px;
}
。メッセージ{
  幅: 400ピクセル;
  高さ: 390ピクセル;
  マージン: 0 自動;
  背景色: 白;
  境界線の半径: 4px;
}
.title2{
  幅: 350ピクセル;
  フォントサイズ: 20px;
  色: #9b9b9b;
  パディング上部: 50px;
  下境界線: 1px 実線 #e6e6e6;
  マージン: 0 自動;
  下マージン: 20px;
}
.ss{
  幅: 350ピクセル;
  高さ: 45px;
  境界線の半径: 4px;
  境界線: 1px 実線 #d9d9d9;
  テキストインデント: 20px;
  フォントサイズ: 14px;
  下マージン: 20px;
}
.pass .t1{
  幅: 350ピクセル;
  マージン: 0 自動;
  高さ: 20px;
  行の高さ: 20px;
  フォントサイズ: 12px;
  テキスト配置: 中央;
  位置: 相対的;
}
.t1 .right{
  位置: 絶対;
  右: 0;
}
.覚えておいてください{
  表示: インラインブロック;
  位置: 絶対;
  左: 20px;
}
.左入力{
  位置: 絶対;
  左:0;
  幅: 14px;
  高さ: 14px;
}
.ログイン_btn{
  幅: 350ピクセル;
  高さ: 45px;
  背景: #ffc210;
  境界線の半径: 5px;
  フォントサイズ: 16px;
  色: #fff;
  文字間隔: .26px;
  上マージン: 30px;
  アウトライン: なし;
  境界線:なし;
  カーソル: ポインタ;
}
。登録する{
  上マージン: 20px;
  フォントサイズ: 14px;
  色: #9b9b9b;
}
.レジスタスパン{
  色: #ffc210;
  カーソル: ポインタ;
}
。カーソル{
  カーソル: ポインタ;
}
。見せる{
  表示: インラインブロック;
  パディング下部: 5px;
  border-bottom: 2px 実線オレンジ;
  色: #4a4a4a;
}
{
  テキスト装飾: なし;
  色: #ffc210;
}
#キャプチャ{
  マージン: 0 自動;
  高さ: 44px;
}
。SMS{
  位置: 相対的;
  幅: 350ピクセル;
  高さ: 45px;
  マージン: 0 自動;
  行の高さ: 45px;
}
.sms .コンテンツ{
  位置: 絶対;
  トップ:0;
  右: 10px;
  色: オレンジ;
  border-left: 1px 実線オレンジ;
  左パディング: 10px;
  カーソル: ポインタ;

}
</スタイル>

フロントエンドは SMS 検証コードを取得します。

//SMS認証コードを取得するget_sms_code:function(){
        let reg = /1[3-9]{2}\d{8}/; //電話番号が実際の電話番号の場合、確認コードを取得できます if( reg.test(this.phone) ){ //ページに「確認コードを取得」と表示されたら、確認コード要求をトリガーできます。カウントダウンが始まったら、クリックしても確認コード要求をトリガーできません if(this.content == "確認コードを取得"){ //確認コード要求を正常に送信すると、60秒間のカウントダウンが開始されます this.content=60;
            _this=this とします。
            tt = setInterval(関数() {
              _this.content>=1の場合{
                _this.content--
              }
              それ以外 {
                _this.content='認証コードを取得する';
                クリア間隔(tt)
              }
            },1000);
            this.$axios.get('http://127.0.0.1:8000/user/sms?type=login&phone='+this.phone)
              .then(関数 (res) {
                res.data.message==0の場合{
                  alert('認証コードが正常に送信されました')
                }
              }).catch(関数(エラー) {
                コンソール.log(エラー.応答)
              })
          }
        }それ以外 {
          アラート('携帯電話番号が間違っています')
        }
      },

フロントエンドでは、携帯電話番号と SMS 確認コードを使用してログインします。

//SMS認証コードを取得するget_sms_code:function(){
        let reg = /1[3-9]{2}\d{8}/; //電話番号が実際の電話番号の場合、確認コードを取得できます if( reg.test(this.phone) ){ //ページに「確認コードを取得」と表示されたら、確認コード要求をトリガーできます。カウントダウンが始まったら、クリックしても確認コード要求をトリガーできません if(this.content == "確認コードを取得"){ //確認コード要求を正常に送信すると、60秒間のカウントダウンが開始されます this.content=60;
            _this=this とします。
            tt = setInterval(関数() {
              _this.content>=1の場合{
                _this.content--
              }
              それ以外 {
                _this.content='認証コードを取得する';
                クリア間隔(tt)
              }
            },1000);
            this.$axios.get('http://127.0.0.1:8000/user/sms?type=login&phone='+this.phone)
              .then(関数 (res) {
                res.data.message==0の場合{
                  alert('認証コードが正常に送信されました')
                }
              }).catch(関数(エラー) {
                コンソール.log(エラー.応答)
              })
          }
        }それ以外 {
          アラート('携帯電話番号が間違っています')
        }
      },

これで、vue_drf の SMS 認証コードの実装に関するこの記事は終了です。vue_drf SMS 認証コードの関連コンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • vue+drf+サードパーティのスライディング検証コードアクセスの実装

<<:  JavaがMySQL 8.0に接続できない問題の解決策

>>:  Docker で最初のアプリケーションをデプロイする方法

推薦する

MySQL 8.0.18 のインストールと設定のグラフィックチュートリアル

学習目標: Windowsシステムを使用してMySQLデータベースをインストールする方法を学びます。...

ダイナミッククロックを実現するJS+CSS

この記事の例では、動的な時計を実装するためのJS + CSSの具体的なコードを参考までに共有していま...

jsを使用してスライダーをドラッグする効果を実現します

この記事では、jsでスライダーをドラッグする方法の具体的なコードを参考までに共有します。具体的な内容...

JS における for、for...in、for...of、forEach の違いと使用例

forループ基本的な構文形式: for(変数の初期化; 条件式; 演算式){ループ本体ステートメント...

docker を使用して複数のネットワーク インターフェースを持つコンテナーを起動する方法の例

コンテナにネットワークインターフェースを追加する1 デフォルトのネットワークモードでコンテナを実行す...

MySQL max_allowed_pa​​cket 設定

max_allowed_pa​​cket は、受け入れるパケットのサイズを設定するために使用される ...

jsvc を使用して tomcat を起動する方法 (通常のユーザーとして実行)

jsvc の紹介実稼働環境では、Tomcat はデーモン モードで実行する必要があります。Tomc...

コンパイル、インストールから設定ファイルの説明まで、中国語でnginxの詳細な説明

この記事では、コンパイルとインストールから設定ファイルの説明まで、Nginx について詳しく紹介しま...

Vue Nativeを使用したモバイルアプリケーションの構築プロセスの完全な記録

目次序文Vue Nativeの機能宣言的レンダリング双方向バインディングVue.js エコシステムの...

XHTML 特殊文字コレクション

注意&#160;ノーブレークスペース = ノーブレークスペース、 iexcl ¡ &...

セマンティック HTML タグの紹介

ここ数年、ウェブサイト開発では DIV+CSS が非常に人気があり、当時は大きな騒動を引き起こしまし...

要素フォーム検証で検証プロンプトをクリアする方法

目次問題のシナリオ:解決: 1. フィールドを個別にチェックする2. フォームフィールドの下のフィー...

CSS3 での 2D および 3D 変換の実装

CSS3 は、要素の 2D 平面変換と視覚的な 3D 空間変換を実装します。2D 変換はより頻繁に使...

Nodejs は JSON 文字列を JSON オブジェクトに変換するエラー解決法

JSON 文字列を JSON オブジェクトに変換するにはどうすればいいですか? JSON.parse...

サラウンドリフレクションロード効果を実現するHTML+CSS

この記事では、主に html + css を使用してサラウンド リフレクション ローディング エフェ...