WeChatアプレットのサイレントログインとカスタムログイン状態の維持の詳細な説明

WeChatアプレットのサイレントログインとカスタムログイン状態の維持の詳細な説明

1. 背景

ミニプログラムでは、openid はミニプログラム/パブリック アカウントのユーザー識別子です。開発者は、ID カードと同様に、この識別子を通じてユーザーを識別できます。

2. サイレントログインとは何ですか?

一般的なアプリケーションでは、ユーザーはフォーム認証を通じてログインし、ユーザー システムを確立します。この一般的なログイン方法は、通常、ユーザーの目に留まるログイン ページ フォームを通じて行われます。

ミニプログラムはWeChatをベースにしているため、WeChatが公式に提供しているAPI機能を使用して、無意識のうちにユーザーID(OpenID)を取得し、ミニプログラム内でユーザーシステムを迅速に構築できます。これはユーザーには認識されず、プログラムが自動的にログインプロセスを完了します。

2.1 ログインプロセスのシーケンス

以下の写真はWeChat公式から引用したものです

アプレットはwx.login()を呼び出してコードを取得し、サーバーにアップロードします。

非同期関数doLogin()をエクスポートします。
 if (isLogin) が false を返す
 ログイン = true
 キャッシュを削除します('トークン')
 const { コード } = wxp.login() を待機します
 const データ = ログインを待機します ({ コード })
 setCache('トークン', data.data.token)
 ログイン = false
 真を返す
}

サーバーはコードを取得し、auth.code2Sessionインターフェースを呼び出してopenidと交換します。
const getOpenid = 非同期関数 (appid, secret, code) {
    const resData = axios.get('https://api.weixin.qq.com/sns/jscode2session?appid=' + appid + '&secret=' + secret + '&js_code=' + code + '&grant_type=authorization_code');
    resData.data を返します。
}

プロセスを要約します。

  • アプレットはwx.login()を呼び出してコードを取得し、サーバーにアップロードします。
  • サーバーはコードを使用し、WeChat auth.code2Sessionインターフェースを呼び出してopenidと交換します。
  • バックエンドサーバーはOpenIDに基づいてカスタムトークンを生成し、フロントエンドに返して保存します。後続のビジネスロジックはトークンを使用してユーザーを識別します。

3. カスタムログイン状態を維持する方法

公式のアプローチを見てみましょう:

wx.checkSession({
  成功 () {
    //session_key は期限切れではなく、このライフサイクル全体を通じて有効です},
  失敗 () {
    //session_key の有効期限が切れているため、ログイン プロセスを再実行する必要があります wx.login() //Re-login}
})

図から、実際にログイン状態を決定するのは WeChat の checkSession インターフェースであることがわかります。したがって、ユーザーのログイン ステータスが有効かどうかを確認するたびに、まず checkSession インターフェイスを呼び出します。session_key が無効な場合は、ログイン プロセスを開始します。

4. サイレントログインの全体的なプロセス

4.1 app.onLaunchでログインが開始される

ほとんどの API 呼び出しではトークンの検証が必要なので、ミニプログラムの起動時に定期的な関数 app.onLaunch でサイレント ログインを開始するのが最も適切です。

4.2 処理アプレットは非同期ブロッキングをサポートしていません

ページレベルおよびコンポーネントレベルのライフサイクル関数は、ミニプログラムの起動プロセスでの非同期ブロッキングをサポートしていないため、app.onLaunch で開始された wx.login が成功する前に、ページレベルのライフサイクル関数が既にサーバーへの要求を開始している状況が発生する可能性があります。ほとんどのインターフェース設計では検証が必要なため、この時点ではログインは成功しておらず、トークンが正しく返されていないため、ページレベルのライフサイクルによって開始されたデータ取得インターフェースは必ずエラーを報告します(たとえば、401が返されます)。

4.2.1 大まかな解決策

コールバック関数の使用

//アプリ.js
this.globalData.wxp.showLoading({
        タイトル: 「ログイン中...」
      });
      ログインを待機します();
      this.globalData.hasLogin = true;
      if (this.checkLoginReadyCallback) {
        this.checkLoginReadyCallback();
      }
      this.globalData.wxp.hideLoading();
      
ページのライフサイクルでは、async onLoad() {
    app.globalData.hasLogin の場合 {
    //すでにログインしている場合は、データを直接取得します this.getUserInfo();
      イベントを取得します。
    } それ以外 {
    // ログインしていないときのコールバック関数を定義し、app.js が正常にログインした後に呼び出します app.checkLoginReadyCallback = async () => {
        this.getUserInfo();
        イベントを取得します。
      };
    }
  },

利点: シンプルで粗雑

デメリット: コード構造が貧弱。複数のページがスタートアップ ページである場合、複数のページに対してコールバック関数を定義する必要があります (ミニ プログラム onShare モードが使用されていると仮定)

4.2.2 エレガントな方法

fly.js ライブラリの助けを借りて、リクエストのロック メカニズムが実装されます。プロセス: app.js でログインが開始され、ページでもリクエストが開始されます。リクエスト インターセプターでは、要求されたインターフェイスがホワイトリスト (トークン検証を必要としないインターフェイス) にあるかどうか、およびインターフェイスとトークンが存在するかどうかを判断します。両方とも false の場合は、現在のリクエストをリクエスト キューにロックし、ログイン プロセスを実行します。ログイン プロセスが成功するまで待機した後、要求キューのロックを解除し、ページ レベルの要求タスクの開始を続行します。以下はリクエスト インターセプターのコードです。

//インターセプト処理 fly.interceptors.request.use(async (request) => {
	// トークンがなくホワイトリストにないリクエストはすべてロックされます (
		!getCache('トークン') &&
		!whiteList.some((item) => request.url.startsWith(item))
	){
		フライ.ロック()
		//ログイン成功後にロックを解除する
		ログインを待つ()
		fly.unlock() //ロック解除後、リクエストキュー内のタスクは引き続き開始されます }

	if (getCache('token') && !fly.config.headers['Authorization']) {
		request.headers['Authorization'] = getCache('token')
	}
	request.headers['Content-Type'] = 'application/x-www-form-urlencoded'

	返品リクエスト
})

もちろん、カスタム ログイン状態も期限切れになる場合があります。処理のために、応答インターセプターでエラーをキャプチャできます。401 トークン有効期限コードが検出されると、リクエスト キューの背後にあるすべてのリクエストをロックして、複数の 401 カスタム ログイン状態の有効期限が切れないようにする必要があります。次に、ログインを開始し、ログインが成功した後にロックを解除して、後続のリクエスト キューの実行をトリガーし、トークンの有効期限切れのためにサーバーによって拒否されたインターフェイスを再実行します。そうしないと、リクエストは失敗します (サイレント ログインはユーザーには認識されないため、認証情報の突然の有効期限切れはユーザーに特に違和感を与えるため、ユーザーがもう一度クリックしたり、他のアクションで開始したりするのではなく、このリクエスト操作を再実行する必要があります)。

// レスポンスインターセプション fly.interceptors.response.use(
	(応答) => {
		//リクエスト結果のデータフィールドのみを返す。response.dataを返す
	},
	非同期(エラー) => {
		(エラーステータス === 401)の場合{
			//401の後、それ以降のすべてのリクエストは再び401にならないようにロックされます
			フライ.ロック()
			キャッシュを削除します('トークン')
			//ログイン成功後にロックを解除する
			const isLoginSuccess = doLogin() を待つ
			ログイン成功の場合
				フライ.ロック解除()
			}
                        // トークンの有効期限切れによりサーバーに拒否されたインターフェースを新たに実行する return fly.request(err.request)
		}
	}
)

リクエストが同時に発生する可能性があるため、ログインが複数回実行されるのを防ぐために、doLogin 関数を少し変更します (エレガントに記述されているわけではありませんが、私の能力には限界があるため、ご教示ください)。

非同期関数doLogin()をエクスポートします。
        //ログイン中の場合は実行しない if (isLogin) return false
	ログイン = true
        // ステータスをログイン済みに変更します。とにかく、複数回ログインします。removeCache('token')
	const { コード } = wxp.login() を待機します
	const データ = ログインを待機します ({ コード })
	setCache('トークン', data.data.token)
	ログイン = false
	真を返す
}

4.3 全体フローチャート

5. 最後に

詳細に注意を払う読者は、API リクエストに設定されたリクエストの最大数がないことに気付くでしょう (WeChat ミニプログラムは、最大 5 つの API の同時開始をサポートします)。これを補足する必要があります。全体的に、実装方法にはまだ改善の余地があると感じています。著者の能力には限界があるため、学習と議論も同時に行っています。

これで、WeChatミニプログラムのサイレントログインとカスタムログインステータスの維持に関するこの記事は終了です。WeChatミニプログラムのサイレントログインに関する関連コンテンツの詳細については、123WORDPRESS.COMの以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後も123WORDPRESS.COMを応援してください。

以下もご興味があるかもしれません:
  • WeChat アプレットサイレントログイン実装コード

<<:  Linux で Redis のリモート接続を実装する方法

>>:  Java は Excel から MySQL にデータをインポートします

推薦する

nginx をシャットダウン/再起動/起動する方法

閉鎖サービス nginx 停止systemctl 停止 nginx起動するサービス nginx 開始...

MySQL をデプロイするときに発生する「テーブル mysql.plugin が存在しません」という問題の解決方法

今日、MySQL の無料インストール版をデプロイしたところ、テーブル 'mysql.plug...

WeChatアプレットは写真アップロード機能を実現

この記事の例では、WeChatアプレットで写真をアップロードするための具体的なコードを参考までに共有...

TinyEditorはシンプルで使いやすいHTML WYSIWYGエディタです

数日前、国産の XHTML エディタを紹介しました。今日は、有名な海外の Web デザイン ブログl...

新しく作成された MySQL ユーザーの % には localhost が含まれていますか?

通常の説明%はどのクライアントでも接続できることを意味しますlocalhostはローカルコンピュータ...

JavaScript の絶妙なスネーク実装プロセス

目次1. HTML構造を作成する2. テーブルを作成する3. ヘビの頭と体を作る4. 食べ物を作る5...

Vue の要素カレンダー コンポーネントを使用したサンプル コード

まず効果図を見てみましょう: 完全なコードは添付されています <テンプレート> <...

Ubuntu 20.04 デスクトップのインストールとルート権限の有効化および SSH インストールの詳細

記事は主にUbuntu 20.04の簡単なインストールプロセスを記録し、インストール後に国内ソースを...

Docker を使用してイメージをローカルにパッケージ化してデプロイする方法

初めてDockerを使用してイメージをローカルにパッケージ化してデプロイするまず、私のラップトップシ...

secure_file_priv nullの問題を解決する

secure_file_priv = ' ';管理者としてcmdを実行します。 my...

Windows Server 2008 64ビット MySQL5.6 インストール不要版 設定方法図

1 公式ウェブサイトから MySQL 5.6 バージョンの圧縮パッケージmysql-5.6.36-w...

HTML テーブルタグチュートリアル (45): テーブル本体タグ

<tbody> タグは、テーブル本体のスタイルを定義するために使用されます。基本構文 &...

MySQLで負荷分散を実装する方法

序文MySQL は、クライアント/サーバー構造に基づく、高速、高性能、マルチスレッドのオープン ソー...

5分でWebRTCビデオチャットを構築する

前回の記事では、Ubuntu 上の webrtc ベースの多人数ビデオチャット サービスの詳細なコー...

Linux deb パッケージの解凍、変更、その他の操作方法のコード例

さまざまな理由により、debパッケージ内のさまざまなファイルの内容を直接変更する必要がある場合があり...