微信小程序靜默登錄和維護自定義登錄態(tài)詳解
1.背景
在小程序中,openid是一個用戶對于一個小程序/公眾號的標識,開發(fā)者可以通過這個標識識別出用戶,就如同你的身份證一樣。
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/jscode2session?appid=' + appid + '&secret=' + secret + '&js_code=' + code + '&grant_type=authorization_code'); return resData.data; }
總結流程:
- 小程序端調用wx.login(),獲取code并且上傳到服務器
- 服務器根據(jù)code,并且調用微信auth.code2Session接口換取openid
- 后臺服務器根據(jù)openid生成自定義token返回前端并且存儲起來,后續(xù)業(yè)務邏輯用token來識別用戶身份
3.如何維護自定義登錄態(tài)
讓我們來看下官方的處理方式:
wx.checkSession({ success () { //session_key 未過期,并且在本生命周期一直有效 }, fail () { // session_key 已經(jīng)失效,需要重新執(zhí)行登錄流程 wx.login() //重新登錄 } })
由圖中我們可以知道,真正決定登錄態(tài)的是微信的checkSession接口。因此每次檢查用戶登錄態(tài)是否有效就先調用一個checkSession接口,如果session_key失效,再發(fā)起登錄流程。
4.靜默登錄整體流程
4.1app.onLaunch中發(fā)起登錄
由于大部分的接口調用都需要token驗證,因此在小程序啟動的周期函數(shù)app.onLaunch中發(fā)起靜默登錄最為合適不過了。
4.2處理小程序不支持異步阻塞
由于小程序的啟動流程中,頁面級和組件級的生命周期函數(shù)都不支持異步阻塞;因此會造成一個情況,app.onLaunch中發(fā)起的wx.login還沒有成功的時候,頁面級的生命周期函數(shù)已經(jīng)向服務器發(fā)起請求。由于我們的接口設計大部分都是需要驗證的,此時登錄還未成功,token也還沒有正確返回,因此頁面級的生命周期發(fā)起的數(shù)據(jù)獲取接口肯定是會報錯的(例如返回了401)
4.2.1粗糙的方案
采用回調函數(shù)的方式
//app.js this.globalData.wxp.showLoading({ title: '登錄中...' }); await login(); this.globalData.hasLogin = true; if (this.checkLoginReadyCallback) { this.checkLoginReadyCallback(); } this.globalData.wxp.hideLoading(); 頁面的生命周期中 async onLoad() { if (app.globalData.hasLogin) { //如果已經(jīng)登錄了直接獲取數(shù)據(jù) this.getUserInfo(); this.getEvent(); } else { //未登錄定義下回調函數(shù),等app.js登錄成功之后進行調用 app.checkLoginReadyCallback = async () => { this.getUserInfo(); this.getEvent(); }; } },
優(yōu)點:簡單粗暴
缺點:代碼結構差;如果是多個頁面為啟動頁,則需要多個頁面都定義回調函數(shù)(假設使用了小程序onShare模式)
4.2.2優(yōu)雅的方式
借助fly.js庫,實現(xiàn)對請求進行上鎖機制。流程:app.js中發(fā)起登錄,同時頁面中也會發(fā)起請求。在請求攔截器中判斷請求的接口是否為白名單(不需要token驗證的接口)接口和token是否存在;如果都為false,鎖住當前請求進入請求隊列,執(zhí)行登錄流程。等待登錄流程成功之后解鎖請求隊列,繼續(xù)發(fā)起頁面級的請求任務。如下為請求攔截器中的代碼:
//攔截處理 fly.interceptors.request.use(async (request) => { //沒有token且請求不是白名單的都鎖住 if ( !getCache('token') && !whiteList.some((item) => request.url.startsWith(item)) ) { fly.lock() //去登陸 成功之后再unlock await doLogin() fly.unlock() //解鎖后,會繼續(xù)發(fā)起請求隊列中的任務 } if (getCache('token') && !fly.config.headers['Authorization']) { request.headers['Authorization'] = getCache('token') } request.headers['Content-Type'] = 'application/x-www-form-urlencoded' return request })
當然,自定義登錄態(tài)也會存在過期的情況,我們可以在響應攔截器中捕獲出錯進行處理:當檢測到401token過期代碼時,需要把請求隊列后面的請求都鎖死,防止多次出現(xiàn)401自定義登錄態(tài)過期的情況,然后發(fā)起登錄,登陸成功之后再進行解鎖行為,觸發(fā)后續(xù)的請求隊列執(zhí)行,并且重新執(zhí)行本次由于token過期被服務器拒絕的接口,否則會造成請求失敗的情況(由于靜默登錄是用戶無感知的,突然出現(xiàn)身份驗證信息過期會使用戶感覺到特別地奇怪,因此需要重新執(zhí)行本次請求操作而不是由用戶再次點擊或者其他的行為再發(fā)起):
// 響應攔截 fly.interceptors.response.use( (response) => { //只將請求結果的data字段返回 return response.data }, async (err) => { if (err.status === 401) { //401之后,把后面的請求都鎖死 防止再次401 fly.lock() removeCache('token') //去登陸 成功之后再unlock const isLoginSuccess = await doLogin() if (isLoginSuccess) { fly.unlock() } //新執(zhí)行本次由于token過期被服務器拒絕的接口 return fly.request(err.request) } } )
由于請求有可能是并發(fā)的,為了防止登錄被多次執(zhí)行,因此對doLogin函數(shù)進行了小小的改造(盡管寫得很不優(yōu)雅,但是能力有限,大佬們賜教了):
export async function doLogin() { //如果正在登錄中則不執(zhí)行 if (isLogin) return false isLogin = true //修改狀態(tài)為登錄中,反正重復多次登錄 removeCache('token') const { code } = await wxp.login() const data = await login({ code }) setCache('token', data.data.token) isLogin = false return true }
4.3 整體流程圖
5.寫在最后
細節(jié)的讀者即可發(fā)現(xiàn),api請求中并未設置最大請求數(shù)量的(微信小程序最大支持五個api同時發(fā)起),這點是需要補充進來的??傮w寫下來作者覺得在實現(xiàn)方式上還有進步的空間,作者能力有限,也是一邊學習一邊探討!
到此這篇關于微信小程序靜默登錄和維護自定義登錄態(tài)的文章就介紹到這了,更多相關微信小程序靜默登錄內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
JavaScript實現(xiàn)谷歌瀏覽器插件開發(fā)的方法詳解
對于瀏覽器插件相信大家都不陌生,誰的瀏覽器不裝幾個好用的插件呢,更是有油猴這個強大的神器。所以本文就來用JavaScript開發(fā)一個谷歌瀏覽器插件,感興趣的小伙伴可以了解一下2022-11-11Iphone手機、安卓手機瀏覽器控制默認縮放大小的方法總結(附代碼)
這篇文章主要介紹了Iphone手機、安卓手機瀏覽器控制默認縮放大小的方法,通過meta標簽中添加屬性代碼展示控制瀏覽器的默認縮放,具體操作步驟大家可查看下文的詳細講解,感興趣的小伙伴們可以參考一下。2017-08-08JavaScript中 ES6 generator數(shù)據(jù)類型詳解
generator 是ES6引入的新的數(shù)據(jù)類型,由function* 定義, (注意*號),接下來通過本文給大家介紹js中 ES6 generator數(shù)據(jù)類型,非常不錯,感興趣的朋友一起學習吧2016-08-08JXTree對象,讀取外部xml文件數(shù)據(jù),生成樹的函數(shù)
JXTree對象,讀取外部xml文件數(shù)據(jù),生成樹的函數(shù)...2007-04-04