溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

微信小程序登錄態(tài)控制深入分析

發(fā)布時間:2020-10-23 08:31:53 來源:腳本之家 閱讀:259 作者:菲麥前端 欄目:web開發(fā)

微信小程序登錄態(tài)控制深入分析

最近微信小程序終于開放了個人注冊,我當(dāng)然不能浪費這個炫技的好機會,“菲麥日程”小程序正在全力推進中,盡請期待~~
在登錄態(tài)控制中,摸索嘗試了小一陣子,特此分享

一、微信建議的登錄態(tài)控制

微信小程序登錄態(tài)控制深入分析

說明:

1)小程序內(nèi)通過wx.login接口獲得code
2)將code傳入后臺,后臺對微信服務(wù)器發(fā)起一個https請求換取openid、session_key
3)后臺生成一個自身的3rd_session(以此為key值保持openid和session_key),返回給前端。

PS:微信方的openid和session_key并沒有發(fā)回給前端小程序

4)小程序拿到3rd_session之后保持在本地
5)小程序請求登錄區(qū)內(nèi)接口,通過wx.checkSession檢查登錄態(tài),如果失效重新走上述登錄流程,否則待上3rd_session到后臺進行登錄驗證

二、可不可以不接受它的建議

不是我反骨,而是我的微信小程序不需要獲取什么私密數(shù)據(jù),用不到session_key,只需要一個openid,微信特別強調(diào)了,為了自身應(yīng)用安全,session_key 不應(yīng)該在網(wǎng)絡(luò)上傳輸,可沒說不可以傳輸openid,那么如果我將openid直接返回給前端小程序,會不會方便很多?下面我們來具體分析下:

永不過期的openid:

要知道,session_key有過期時間,必須適時重新獲取,而針對每一個小程序,唯一標(biāo)識用戶的openid可不會過期,如果只在用戶第一次登錄的時候,通過后臺請求到openid,小程序緩存到本地,之后每次請求都以這個openid作為唯一憑證,豈不是一本萬利~~

事實上,上面的做法忽略了一個致命的問題,手機上是可以切換微信賬戶的,如果手機I上原先登錄了賬戶A,已經(jīng)保存了用戶A的openid,有一天手機I上切換到了賬戶B上,小程序檢測到openid存在,并不會重新獲取openid,那么賬戶B就請求到了賬戶A的數(shù)據(jù),這就造成數(shù)據(jù)亂象了

登錄態(tài)過期后重新獲取openid:

上述的問題并不能打消我使用openid作為登錄憑證的念頭,只需要稍作改進,數(shù)據(jù)就不會亂竄:每次進入小程序通過wx.checkSession檢測登錄是否失效,如果失效重新獲取openid,要知道,手機切換了登錄賬號,登錄態(tài)一定會過期,這樣雖不能一本萬利,但也足夠省心。

這個時候應(yīng)該有一個然而,以永不過期的openid作為登錄憑證,并不是明智之舉,一旦被人截獲,就再也沒有翻身的機會了,而維護一個第三發(fā)的session,至少擁有有效期,這在很大程度上增加了安全性。并且,現(xiàn)在不需要使用session_key,不代表以后,保持系統(tǒng)的可擴展性,才能以不變應(yīng)萬變

事實證明,我還是應(yīng)該接受它的建議

三、基于redis維護3rd_session

維護3rd_session需要一個內(nèi)存數(shù)據(jù)庫,這里我選用了redis

維護會話態(tài)是內(nèi)存數(shù)據(jù)庫的典型應(yīng)用場景,畢竟量小,并且要求速度快,這么一個小應(yīng)用,當(dāng)然也可以自己在內(nèi)存中維護一個對象來進行會話id的處理,但是肯定難以跟一個成熟的系統(tǒng)相媲美

拋開代碼實現(xiàn),這似乎就是一句話可以概括的事情,生成一個唯一的隨機串sessionid,以此為key,openid和微信方的session_key為value存入redis,并把sessionid傳回給客戶端。

但是,翻遍小程序的官方文檔,除了一句據(jù)說的wx.checkSession對開發(fā)者來說是透明的,并沒有小程序登錄態(tài)何時過期的具體說明,如何才能同步前后端的會話過期時間呢?

四、前后端會話過期時間同步

一開始,我還是試圖尋找小程序的登錄態(tài)時效

  {"session_key":"...","expires_in":7200,"openid":"..."}

在code2session接口返回的數(shù)據(jù)中,有一個可疑的字段expires_in,它的值是7200,似乎存儲到redis中的sessionid設(shè)置為7200就可以同步了??墒菍嵺`的結(jié)果再次讓人失望,不管是設(shè)置成7200還是60*60*24(一天),都出現(xiàn)了小程序會話尚在有效期,而服務(wù)器端會話已經(jīng)過期的情況,這直接導(dǎo)致了小程序帶著已經(jīng)緩存的sessionid到服務(wù)器端請求接口,返回未登錄的情況

看來還是只有wx.checkSession才知道小程序會話啥時候過期,于是,作戰(zhàn)方案重新做了調(diào)整,如果wx.checkSession檢測到會話失效,那么帶上已經(jīng)緩存在本地的sessionid(如果有的話),重新發(fā)起登錄請求,后臺從code2session中拿到新的請求結(jié)果后,生成新的隨機sessionid并入庫reids,并且把老的sessionid移除(如果有的話)

當(dāng)然不移除也不會帶來什么功能上的影響,但是會存在兩個問題,首先,跟使用open_id作為登錄憑證一樣,舊的sessionid永不過期,其次,無用的session數(shù)據(jù)占用redis資源,會拖垮訪問性能

五、“脫貧致富指數(shù)”統(tǒng)計

我給小程序的用戶數(shù)安了一個高大上的名字“脫貧致富指數(shù)”,純屬娛樂,切勿當(dāng)真

為了統(tǒng)計使用小程序的用戶數(shù),需要一個表來保存用戶數(shù)據(jù),后臺提供一個接口,讓小程序?qū)⒂脩魯?shù)據(jù)傳上來進行一個注冊操作,當(dāng)然可以把這個功能合并到登錄接口上,每次登錄都把前端小程序獲得的微信用戶數(shù)據(jù)帶上,如果發(fā)現(xiàn)數(shù)據(jù)庫中還沒有該用戶的信息,則進行入庫操作

不難發(fā)現(xiàn),其實只需要用戶第一次登錄的時候注冊一次就行了,所以上述方法雖然簡便,但是有點浪費帶寬,所以應(yīng)該額外提供一個注冊接口,登錄接口只需要返回一個用戶是否已經(jīng)注冊的標(biāo)志,讓客戶端決定是否需要獲取用戶信息,進行注冊操作(當(dāng)然后臺也不會讓同一個用戶重復(fù)入庫)

那么問題就變成如何判斷用戶是第一次登錄了:

1)判斷登錄請求中有沒有帶上sessionid,如果沒帶上,肯定是第一次登錄;如果帶上了就是登錄過的用戶?不,別忘了,前面說過,用戶可能會在同一設(shè)備切換賬戶,那就有可能在登錄接口中帶上了別人sessionid,那并不能表明用戶曾經(jīng)登錄過

2)通過帶上來的sessionid從redis中拿到openid,跟在code2session新請求到的openid進行比對,如果一致,可以證明用戶曾經(jīng)登錄過,否則,仍需要用戶進行注冊

總結(jié)

時間是浪費了那么一些,但是進過思考摸索,代碼肯定更完備了~~

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI