1. 程式人生 > 程式設計 >微信小程式靜默登入和維護自定義登入態詳解

微信小程式靜默登入和維護自定義登入態詳解

1.背景

在小程式中,openid是一個使用者對於一個小程式/公眾號的標識,開發者可以通過這個標識識別出使用者,就如同你的身份證一樣。

2.什麼是靜默登入?

在普通的應用中,使用者通過表單驗證登入建立使用者體系,這種常見的登入方式一般是通過登入頁面表單進行登入,對使用者來說是有感的。

在小程式中,由於是基於微信,可以通過微信官方提供的API能力,使我們能夠無感知得獲取使用者身份標識(openid),快速建立小程式內的使用者體系,對使用者來說是無感知的,因此是由程式來完成這個自動的登陸過程。

2.1登入流程時序

下圖取自微信官方

微信小程式靜默登入和維護自定義登入態詳解

小程式端呼叫wx.login(),獲取code並且上傳到伺服器

export async function doLogin() {
 if (isLogin) return false
 isLogin = true
 removeCache('token')
 const { code } = await wxp.login()
 const data = await login({ code })
 setCache('token',data.data.token)
 isLogin = false
 return true
}

服務端拿到code,呼叫auth.code2Session介面換取openid
const getOpenid = async function (appid,secret,code) {
    const resData = await axios.get('https://api.weixin.qq.com/sns/
js
code2session?appid=' + appid + '&secret=' + secret + '&js_code=' + code + '&grant_type=authorization_code'); return resData.data; }

總結流程:

  • 小程式端呼叫wx.login(),獲取code並且上傳到伺服器
  • 伺服器根據code,並且呼叫微信auth.code2Session介面換取openid
  • 後臺伺服器根據openid生成自定義token返回前端並且儲存起來,後續業務邏輯用token來識別使用者身份

3.如何維護自定義登入態

讓我們來看下官方的處理方式:

微信小程式靜默登入和維護自定義登入態詳解

wx.checkSession({
  success () {
    //session_key 未過期,並且在本生命週期一直有效
  },fail () {
    // session_key 已經失效,需要重新執行登入流程
    wx.login() //重新登入
  }
})

由圖中我們可以知道,真正決定登入態的是微信的checkSession介面。因此每次檢查使用者登入態是否有效就先呼叫一個checkSession介面,如果session_key失效,再發起登入流程。

4.靜默登入整體流程

4.1app.onLaunch中發起登入

由於大部分的介面呼叫都需要token驗證,因此在小程式啟動的周期函式app.onLaunch中發起靜默登入最為合適不過了。

微信小程式靜默登入和維護自定義登入態詳解

4.2處理小程式不支援非同步阻塞

由於小程式的啟動流程中,頁面級和元件級的生命週期函式都不支援非同步阻塞;因此會造成一個情況,app.onLaunch中發起的wx.login還沒有成功的時候,頁面級的生命週期函式已經向伺服器發起請求。由於我們的介面設計大部分都是需要驗證的,此時登入還未成功,token也還沒有正確返回,因此頁面級的生命週期發起的資料獲取介面肯定是會報錯的(例如返回了401)

4.2.1粗糙的方案

採用回撥函式的方式

//app.js
this.globalData.wxp.showLoading({
        title: '登入中...'
      });
      await login();
      this.globalData.hasLogin = true;
      if (this.checkLoginReadyCallback) {
        this.checkLoginReadyCallback();
      }
    www.cppcns.com  this.globalData.wxp.hideLoading();
      
頁面的生命週期中
async onLoad() {
    if (app.globalData.hasLogin) {
    //如果ypCIu已經登入了直接獲取資料
      this.getUserInfo();
      this.getEvent();
    } else {
    //未登入定義下回調函式,等app.js登入成功之後進行呼叫
      app.checkLoginReadyCallback = async () => {
        this.getUserInfo();
        this.getEvent();
      };
    }
  },

優點:簡單粗暴

缺點:程式碼結構差;如果是多個頁面為啟動頁,則需要多個頁面都定義回撥函式(假設使用了小程式onShare模式)

4.2.2優雅的方式

藉助fly.js庫,實現對請求進行上鎖機制。流程:app.js中發起登入,同時頁面中也會發起請求。在請求攔截器中判斷請求的介面是否為白名單(不需要token驗證的介面)介面和token是否存在;如果都為false,鎖住當前請求進入請求佇列,執行登入流程。等待登入流程成功之後解鎖請求佇列,繼續發起頁面級的請求任務。如下為請求攔截器中的程式碼:

//攔截處理
fly.interceptors.request.use(async (request) => {
	//沒有token且請求不是白名單的都鎖住
	if (
		!getCache('token') &&
		!whiteList.some((item) => request.url.startsWith(item))
	) {
		fly.lock()
		//去登陸 成功之後再unlock
		await doLogin()
		fly.unlock() //解鎖後,會繼續發起請求佇列中的任務
	}

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

	return request
})

當然,自定義登入態也會存在過期的情況,我們可以在響應攔截器中捕獲出錯進行處理:當檢測到401t程式設計客棧oken過期程式碼時,需要把請求佇列後面的請求都鎖死,防止多次出現401自定義登入態過期的情況,然後發起登入,登陸成功之後再進行解鎖行為,觸發後續的請求佇列執行,並且重新執行本次由於token過期被伺服器拒絕的介面,否則會造成請求失敗的情況(由於靜默登入是使用者無感知的,突然出現身份驗證資訊過期會使使用者感覺到特別地奇怪,因此www.cppcns.com需要重新執行本次請求操作而不是由使用者再次點選或者其他的行為再發起):

// 響應攔截
fly.interceptors.response.use(
	(response) => {
		//只將請求結果的data欄位返回
		return response.data
	},async (err) => {
		if (err.status === 401) {
			//401之後,把後面的請求都鎖死 防止再次401
			fly.lock()
			removeCache('token')
			//去登陸 成功之後再unlock
			const isLoginSucc程式設計客棧ess = await doLogin()
			if (isLoginSuccess) {
				fly.unlock()
			}
                        //新執行本次由於token過期被伺服器拒絕的介面
			return fly.request(err.request)
		}
	}
)

由於請求有可能是併發的,為了防止登入被多次執行,因此對doLogin函式進行了小小的改造(儘管寫得很不優雅,但是能力有限,大佬們賜教了):

export async function doLogin() {
        //如果正在登入中則不執行
	if (isLogin) return false
	isLogin = true
        //修改狀態為登入中,反正重複多次登入
	removeCache('token')
	const { code } = await wxp.login()
	const data = await login({ code })
	setCache('token',data.data.token)
	isLogin = false
	return true
}

4.3 整體流程圖

微信小程式靜默登入和維護自定義登入態詳解

5.寫在最後

細節的讀者即可發現,api請求中並未設定最大請求數量的(微信小程式最大支援五個api同時發起),這點是需要補充進來的。總體寫下來作者覺得在實現方式上還有進步的空間,作者能力有限,也是一邊學習一邊探討!

到此這篇關於微信小程式靜默登入和維護自定義登入態的文章就介紹到這了,更多相關微信小程式靜默登入內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!