亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

微信小程序靜默登錄和維護(hù)自定義登錄態(tài)詳解

 更新時(shí)間:2021年05月08日 14:42:08   作者:羅哥哥  
這篇文章主要給大家介紹了關(guān)于微信小程序靜默登錄和維護(hù)自定義登錄態(tài)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

1.背景

在小程序中,openid是一個(gè)用戶(hù)對(duì)于一個(gè)小程序/公眾號(hào)的標(biāo)識(shí),開(kāi)發(fā)者可以通過(guò)這個(gè)標(biāo)識(shí)識(shí)別出用戶(hù),就如同你的身份證一樣。

2.什么是靜默登錄?

在普通的應(yīng)用中,用戶(hù)通過(guò)表單驗(yàn)證登錄建立用戶(hù)體系,這種常見(jiàn)的登錄方式一般是通過(guò)登錄頁(yè)面表單進(jìn)行登錄,對(duì)用戶(hù)來(lái)說(shuō)是有感的。

在小程序中,由于是基于微信,可以通過(guò)微信官方提供的API能力,使我們能夠無(wú)感知得獲取用戶(hù)身份標(biāo)識(shí)(openid),快速建立小程序內(nèi)的用戶(hù)體系,對(duì)用戶(hù)來(lái)說(shuō)是無(wú)感知的,因此是由程序來(lái)完成這個(gè)自動(dòng)的登陸過(guò)程。

2.1登錄流程時(shí)序

下圖取自微信官方

小程序端調(diào)用wx.login(),獲取code并且上傳到服務(wù)器

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
}

服務(wù)端拿到code,調(diào)用auth.code2Session接口換取openid
const getOpenid = async function (appid, secret, code) {
    const resData = await axios.get('https://api.weixin.qq.com/sns/jscode2session?appid=' + appid + '&secret=' + secret + '&js_code=' + code + '&grant_type=authorization_code');
    return resData.data;
}

總結(jié)流程:

  • 小程序端調(diào)用wx.login(),獲取code并且上傳到服務(wù)器
  • 服務(wù)器根據(jù)code,并且調(diào)用微信auth.code2Session接口換取openid
  • 后臺(tái)服務(wù)器根據(jù)openid生成自定義token返回前端并且存儲(chǔ)起來(lái),后續(xù)業(yè)務(wù)邏輯用token來(lái)識(shí)別用戶(hù)身份

3.如何維護(hù)自定義登錄態(tài)

讓我們來(lái)看下官方的處理方式:

wx.checkSession({
  success () {
    //session_key 未過(guò)期,并且在本生命周期一直有效
  },
  fail () {
    // session_key 已經(jīng)失效,需要重新執(zhí)行登錄流程
    wx.login() //重新登錄
  }
})

由圖中我們可以知道,真正決定登錄態(tài)的是微信的checkSession接口。因此每次檢查用戶(hù)登錄態(tài)是否有效就先調(diào)用一個(gè)checkSession接口,如果session_key失效,再發(fā)起登錄流程。

4.靜默登錄整體流程

4.1app.onLaunch中發(fā)起登錄

由于大部分的接口調(diào)用都需要token驗(yàn)證,因此在小程序啟動(dòng)的周期函數(shù)app.onLaunch中發(fā)起靜默登錄最為合適不過(guò)了。

4.2處理小程序不支持異步阻塞

由于小程序的啟動(dòng)流程中,頁(yè)面級(jí)和組件級(jí)的生命周期函數(shù)都不支持異步阻塞;因此會(huì)造成一個(gè)情況,app.onLaunch中發(fā)起的wx.login還沒(méi)有成功的時(shí)候,頁(yè)面級(jí)的生命周期函數(shù)已經(jīng)向服務(wù)器發(fā)起請(qǐng)求。由于我們的接口設(shè)計(jì)大部分都是需要驗(yàn)證的,此時(shí)登錄還未成功,token也還沒(méi)有正確返回,因此頁(yè)面級(jí)的生命周期發(fā)起的數(shù)據(jù)獲取接口肯定是會(huì)報(bào)錯(cuò)的(例如返回了401)

4.2.1粗糙的方案

采用回調(diào)函數(shù)的方式

//app.js
this.globalData.wxp.showLoading({
        title: '登錄中...'
      });
      await login();
      this.globalData.hasLogin = true;
      if (this.checkLoginReadyCallback) {
        this.checkLoginReadyCallback();
      }
      this.globalData.wxp.hideLoading();
      
頁(yè)面的生命周期中
async onLoad() {
    if (app.globalData.hasLogin) {
    //如果已經(jīng)登錄了直接獲取數(shù)據(jù)
      this.getUserInfo();
      this.getEvent();
    } else {
    //未登錄定義下回調(diào)函數(shù),等app.js登錄成功之后進(jìn)行調(diào)用
      app.checkLoginReadyCallback = async () => {
        this.getUserInfo();
        this.getEvent();
      };
    }
  },

優(yōu)點(diǎn):簡(jiǎn)單粗暴

缺點(diǎn):代碼結(jié)構(gòu)差;如果是多個(gè)頁(yè)面為啟動(dòng)頁(yè),則需要多個(gè)頁(yè)面都定義回調(diào)函數(shù)(假設(shè)使用了小程序onShare模式)

4.2.2優(yōu)雅的方式

借助fly.js庫(kù),實(shí)現(xiàn)對(duì)請(qǐng)求進(jìn)行上鎖機(jī)制。流程:app.js中發(fā)起登錄,同時(shí)頁(yè)面中也會(huì)發(fā)起請(qǐng)求。在請(qǐng)求攔截器中判斷請(qǐng)求的接口是否為白名單(不需要token驗(yàn)證的接口)接口和token是否存在;如果都為false,鎖住當(dāng)前請(qǐng)求進(jìn)入請(qǐng)求隊(duì)列,執(zhí)行登錄流程。等待登錄流程成功之后解鎖請(qǐng)求隊(duì)列,繼續(xù)發(fā)起頁(yè)面級(jí)的請(qǐng)求任務(wù)。如下為請(qǐng)求攔截器中的代碼:

//攔截處理
fly.interceptors.request.use(async (request) => {
	//沒(méi)有token且請(qǐng)求不是白名單的都鎖住
	if (
		!getCache('token') &&
		!whiteList.some((item) => request.url.startsWith(item))
	) {
		fly.lock()
		//去登陸 成功之后再u(mài)nlock
		await doLogin()
		fly.unlock() //解鎖后,會(huì)繼續(xù)發(fā)起請(qǐng)求隊(duì)列中的任務(wù)
	}

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

	return request
})

當(dāng)然,自定義登錄態(tài)也會(huì)存在過(guò)期的情況,我們可以在響應(yīng)攔截器中捕獲出錯(cuò)進(jìn)行處理:當(dāng)檢測(cè)到401token過(guò)期代碼時(shí),需要把請(qǐng)求隊(duì)列后面的請(qǐng)求都鎖死,防止多次出現(xiàn)401自定義登錄態(tài)過(guò)期的情況,然后發(fā)起登錄,登陸成功之后再進(jìn)行解鎖行為,觸發(fā)后續(xù)的請(qǐng)求隊(duì)列執(zhí)行,并且重新執(zhí)行本次由于token過(guò)期被服務(wù)器拒絕的接口,否則會(huì)造成請(qǐng)求失敗的情況(由于靜默登錄是用戶(hù)無(wú)感知的,突然出現(xiàn)身份驗(yàn)證信息過(guò)期會(huì)使用戶(hù)感覺(jué)到特別地奇怪,因此需要重新執(zhí)行本次請(qǐng)求操作而不是由用戶(hù)再次點(diǎn)擊或者其他的行為再發(fā)起):

// 響應(yīng)攔截
fly.interceptors.response.use(
	(response) => {
		//只將請(qǐng)求結(jié)果的data字段返回
		return response.data
	},
	async (err) => {
		if (err.status === 401) {
			//401之后,把后面的請(qǐng)求都鎖死 防止再次401
			fly.lock()
			removeCache('token')
			//去登陸 成功之后再u(mài)nlock
			const isLoginSuccess = await doLogin()
			if (isLoginSuccess) {
				fly.unlock()
			}
                        //新執(zhí)行本次由于token過(guò)期被服務(wù)器拒絕的接口
			return fly.request(err.request)
		}
	}
)

由于請(qǐng)求有可能是并發(fā)的,為了防止登錄被多次執(zhí)行,因此對(duì)doLogin函數(shù)進(jìn)行了小小的改造(盡管寫(xiě)得很不優(yōu)雅,但是能力有限,大佬們賜教了):

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

4.3 整體流程圖

5.寫(xiě)在最后

細(xì)節(jié)的讀者即可發(fā)現(xiàn),api請(qǐng)求中并未設(shè)置最大請(qǐng)求數(shù)量的(微信小程序最大支持五個(gè)api同時(shí)發(fā)起),這點(diǎn)是需要補(bǔ)充進(jìn)來(lái)的??傮w寫(xiě)下來(lái)作者覺(jué)得在實(shí)現(xiàn)方式上還有進(jìn)步的空間,作者能力有限,也是一邊學(xué)習(xí)一邊探討!

到此這篇關(guān)于微信小程序靜默登錄和維護(hù)自定義登錄態(tài)的文章就介紹到這了,更多相關(guān)微信小程序靜默登錄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論