1. 需要1. 需要ウェブサイトを開発している場合、多くの場合、ログインページでは携帯電話番号を使用してテキストメッセージの検証コードを受信してからログインすることができます。今日はこの機能を実行してみましょう。 疑似コード:
テキスト メッセージを送信し、ユーザーがテキスト メッセージを受信できるようにするには、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 を応援していただければ幸いです。 以下もご興味があるかもしれません:
|
<<: JavaがMySQL 8.0に接続できない問題の解決策
>>: Docker で最初のアプリケーションをデプロイする方法
学習目標: Windowsシステムを使用してMySQLデータベースをインストールする方法を学びます。...
この記事の例では、動的な時計を実装するためのJS + CSSの具体的なコードを参考までに共有していま...
この記事では、jsでスライダーをドラッグする方法の具体的なコードを参考までに共有します。具体的な内容...
forループ基本的な構文形式: for(変数の初期化; 条件式; 演算式){ループ本体ステートメント...
コンテナにネットワークインターフェースを追加する1 デフォルトのネットワークモードでコンテナを実行す...
max_allowed_packet は、受け入れるパケットのサイズを設定するために使用される ...
jsvc の紹介実稼働環境では、Tomcat はデーモン モードで実行する必要があります。Tomc...
この記事では、コンパイルとインストールから設定ファイルの説明まで、Nginx について詳しく紹介しま...
目次序文Vue Nativeの機能宣言的レンダリング双方向バインディングVue.js エコシステムの...
注意 ノーブレークスペース = ノーブレークスペース、 iexcl ¡ &...
ここ数年、ウェブサイト開発では DIV+CSS が非常に人気があり、当時は大きな騒動を引き起こしまし...
目次問題のシナリオ:解決: 1. フィールドを個別にチェックする2. フォームフィールドの下のフィー...
CSS3 は、要素の 2D 平面変換と視覚的な 3D 空間変換を実装します。2D 変換はより頻繁に使...
JSON 文字列を JSON オブジェクトに変換するにはどうすればいいですか? JSON.parse...
この記事では、主に html + css を使用してサラウンド リフレクション ローディング エフェ...