まとめ最近、antd pro を使用してプロジェクトを開発しているときに、ユーザー名とパスワードなどの以前のログイン方法を使用する代わりに、ログイン インターフェイスで SMS 検証コードを使用してログインするという新しい要件に遭遇しました。 この方法では SMS 料金が追加されますが、セキュリティが大幅に向上します。Antd にはカウントダウン ボタンが組み込まれていません。 全体的なプロセスSMS 認証コードによるログインのプロセスは非常に簡単です。
フロントエンドページコードReact をインポートし、{useState} を 'react' から取得します。 'umi' から connect をインポートします。 'antd' から { message } をインポートします。 '@ant-design/pro-form' から ProForm、{ ProFormText、ProFormCaptcha } をインポートします。 '@ant-design/icons' から { MobileTwoTone、MailTwoTone } をインポートします。 '@/services/login' から { sendSmsCode } をインポートします。 const ログイン = (props) => { const [countDown, handleCountDown] = useState(5); const { ディスパッチ } = props; const [フォーム] = ProForm.useForm(); 戻る ( <div スタイル={{ 幅: 330, マージン: 'auto'、 }} > <プロフォーム フォーム={フォーム} 提出者={{ 検索設定: { 送信テキスト: 'ログイン', }, レンダリング: (_, dom) => dom.pop(), 送信ボタンプロパティ: { サイズ: 「大」、 スタイル: { 幅: '100%'、 }, }, onSubmit: 非同期() => { const fieldsValue = form.validateFields() を待機します。 console.log(フィールド値); ディスパッチを待つ({ タイプ: 'ログイン/ログイン'、 ペイロード: { ユーザー名: fieldsValue.mobile、 SMS コード: fieldsValue.code }, }); }, }} > <ProFormText フィールドプロパティ={{ サイズ: 「大」、 プレフィックス: <MobileTwoTone />, }} 名前="モバイル" placeholder="電話番号を入力してください" ルール={[ { 必須: true、 メッセージ: 「電話番号を入力してください」 }, { パターン: 新しい正規表現(/^1[3-9]\d{9}$/, 'g'), メッセージ: 「電話番号の形式が正しくありません」 }, ]} /> <ProFormCaptcha フィールドプロパティ={{ サイズ: 「大」、 プレフィックス: <MailTwoTone />, }} countDown={countDown} キャプチャプロパティ={{ サイズ: 「大」、 }} 名前="コード" ルール={[ { 必須: true、 メッセージ: '確認コードを入力してください! '、 }, ]} placeholder="確認コードを入力してください" onGetCaptcha={非同期(モバイル) => { (!form.getFieldValue('モバイル')){ message.error('まず電話番号を入力してください'); 戻る; } m = form.getFieldsError(['mobile']); とします。 (m[0].errors.length > 0)の場合{ メッセージ.エラー(m[0].エラー[0]); 戻る; } 応答を待機します。sendSmsCode(mobile); if (response.code === 10000) message.success('確認コードが正常に送信されました!'); それ以外の場合は、message.error(response.message); }} /> </プロフォーム> </div> ); }; デフォルトの connect()(Login) をエクスポートします。 検証コードとログイン サービスをリクエストする (src/services/login.js)'@/utils/request' からリクエストをインポートします。 非同期関数login(params)をエクスポートします。 リクエストを返します('/api/v1/login', { メソッド: 'POST'、 データ: パラメータ、 }); } 非同期関数 sendSmsCode(mobile) をエクスポートします。 リクエストを返します(`/api/v1/send/smscode/${mobile}`, { メソッド: 'GET'、 }); } ログインを処理するモデル (src/models/login.js)'querystring' から { stringify } をインポートします。 'umi' から { history } をインポートします。 '@/services/login' から { login } をインポートします。 '@/utils/utils' から getPageQuery をインポートします。 'antd' から { message } をインポートします。 'md5' から md5 をインポートします。 定数モデル = { 名前空間: 'ログイン', 状態: ''、 ログインタイプ: ''、 州: { トークン: ''、 }, 効果: *ログイン({ ペイロード }, { 呼び出し、配置 }) { ペイロード.client = 'admin'; // ペイロード.パスワード = md5(ペイロード.パスワード); const response = yield call(ログイン、ペイロード); (レスポンスコード!== 10000)の場合{ メッセージ.エラー(応答.メッセージ); 戻る; } // トークンをローカルストレージに設定する (window.localStorage)の場合{ window.localStorage.setItem('jwt-token', response.data.token); } イールドプット({ タイプ: 'changeLoginStatus'、 ペイロード: { データ: response.data、ステータス: response.status、ログインタイプ: response.loginType }, }); // ログインに成功しました const urlParams = 新しい URL(window.location.href); 定数パラメータ = getPageQuery(); { リダイレクト } = パラメータ; console.log(リダイレクト); if (リダイレクト) { const redirectUrlParams = 新しい URL(リダイレクト); (redirectUrlParams.origin === urlParams.origin)の場合{ リダイレクト = redirect.substr(urlParams.origin.length); リダイレクトマッチ(/^\/.*#/)の場合 リダイレクト = redirect.substr(redirect.indexOf('#') + 1); } } それ以外 { window.location.href = '/home'; } } history.replace(リダイレクト || '/home'); }, ログアウト() { const { redirect } = getPageQuery(); // 注意: セキュリティ上の問題がある可能性がありますので、ご注意ください window.localStorage.removeItem('jwt-token'); if (window.location.pathname !== '/user/login' && !redirect) { 履歴を置き換える({ パス名: '/user/login', 検索: 文字列化({ リダイレクト: window.location.href、 })、 }); } }, }, リデューサー: { changeLoginStatus(状態、{ペイロード}) { 戻る { ...州、 トークン: payload.data.token、 ステータス: ペイロードステータス、 ログインタイプ: ペイロード.ログインタイプ、 }; }, }, }; デフォルトモデルをエクスポートします。 後部バックエンドには主に 2 つのインターフェースがあり、1 つは SMS 検証コードを送信するためのもので、もう 1 つはログイン検証のためのものです。 ルーティング コード スニペット: apiV1.POST("/ログイン", authMiddleware.LoginHandler) apiV1.GET("/send/smscode/:mobile", コントローラー.SendSmsCode) SMS認証コードの処理
次のコードは 6 桁の数字を生成します。乱数が 6 桁未満の場合は、先頭に 0 を追加します。 r := rand.New(rand.NewSource(time.Now().UnixNano())) コード:= fmt.Sprintf("%06v", r.Int31n(1000000)) SMS APIを呼び出す 簡単です。購入したSMSインターフェースの指示に従って呼び出すだけです。 確認のために確認コードを保存してください ここで注意すべき点は、認証コードには有効期限があり、1 つの認証コードを常に使用できるわけではないということです。 パッケージ ユーティリティ 輸入 ( 「fmt」 「数学/ランド」 「同期」 "時間" ) loginItem構造体型{ SMSコード文字列 smsコード有効期限 int64 } LoginMap構造体型{ m map[文字列]*ログイン項目 同期ミューテックス } var lm *ログインマップ InitLoginMap関数(resetTime int64、loginTryMax int) { lm = &ログインマップ{ m: make(map[文字列]*ログイン項目)、 } } func GenSmsCode(キー文字列) 文字列 { r := rand.New(rand.NewSource(time.Now().UnixNano())) コード:= fmt.Sprintf("%06v", r.Int31n(1000000)) _の場合、ok := lm.m[key]; !ok { lm.m[キー] = &ログインアイテム{} } v := lm.m[キー] v.smsCode = コード v.smsCodeExpire = time.Now().Unix() + 600 // 認証コードは10分で期限切れになります return code } func CheckSmsCode(キー、コード文字列) エラー { _の場合、ok := lm.m[key]; !ok { return fmt.Errorf("検証コードは送信されませんでした") } v := lm.m[キー] // 認証コードは期限切れですか? if time.Now().Unix() > v.smsCodeExpire { return fmt.Errorf("検証コード (%s) の有効期限が切れています", code) } // 検証コードは正しいか if code != v.smsCode { return fmt.Errorf("検証コード (%s) が正しくありません", code) } nilを返す } ログイン認証ログイン検証コードは比較的単純で、まず上記の CheckSmsCode メソッドを呼び出して、それが正当かどうかを確認します。 よくある質問Antd バージョンの問題antd pro の ProForm を使用するには、最新バージョンの antd (できれば v4.8 以上) を使用する必要があります。そうでない場合、フロントエンド コンポーネントに互換性のないエラーが発生します。 最適化できるポイント上記の実装は比較的大まかであり、次の側面をさらに最適化できます。 確認コードは、あまり頻繁に送信する必要はありません。結局のところ、SMS メッセージを送信するにはコストがかかります。確認コードはメモリ内に直接保存されるため、システムを再起動すると失われます。redis などのストレージに保存することを検討できます。 antd pro に基づく SMS 認証コード ログイン機能 (プロセス分析) に関するこの記事はこれで終わりです。 antd pro 認証コード ログインに関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。 今後とも 123WORDPRESS.COM を応援していただければ幸いです。 以下もご興味があるかもしれません:
|
<<: Linux のファイル権限とグループ変更コマンドの詳細な説明
HTML デザインパターン学習ノート今週は主にHTMLデザインパターンを学びました。学習内容をまとめ...
CSS を使用してすべての子要素を再帰的に選択するにはどうすればよいですか?以下の記事では、CSS ...
以下はcentos7での設定方法ですsystemc ソース パッケージをダウンロード: System...
前回、Taobaoの詳細ページを分析した後(クリックして表示)、ショッピングモールの基本テンプレート...
目次1. 材料を準備する2. Linuxカーネルファイルをダウンロードする3. コンパイル4. TF...
DockerでNginxイメージをダウンロードする docker プル nginx Docker イ...
1. MySQLイメージをダウンロードするコマンド: docker pull mysql 2. コン...
小さな画像をクリックしたときに更新せずに大きな画像コードが表示されるようにLightboxを実現する...
「通常 1em=16px」と言うのはなぜですか?ユーザーのブラウザによってレンダリングされるデフォル...
序文実稼働環境で Docker を使用する場合、多くの場合、データを複数のコンテナ間で永続化または共...
目次1. はじめに2. ソリューションの実装2.1 実装コード2.2 コードの説明2.3 検証結果1...
復帰文字 ( Ctrl+M ) に不安を感じても心配しないでください。それらを排除する簡単な方法がい...
目次1. はじめに2. Vue JS のパフォーマンス最適化が必要な理由は何ですか? 3. Vueの...
MySQL DDL ステートメントDDL、DMLとは何ですか。 DDL はデータ定義言語であり、CR...
目次1. 解体のヒント2. デジタルセパレーター3. try...catch...finally が...