1. 程式人生 > >小程式:授權、登入、session_key、unionId

小程式:授權、登入、session_key、unionId

微信應用的一個很大的優勢就在於使用過程中是不需要進行註冊和顯式登入的,大部分問題基本上可以一鍵解決。但是在授權、登入和獲取使用者資訊的過程中都發生了哪些事情,今天我們就來討論一下。這篇文章主要分析以下幾個問題:

  • 授權和登入的意義
  • session_key 的作用
  • unionId 的作用,有哪些獲取途徑
  • 在應用中如何儲存使用者登入態

1. 授權和登入的意義

首先必須要明白,授權和登入實際上是兩個操作。

1.1 授權(已廢棄)

那授權的作用是啥呢?從小程式官方文件中我們可以看到授權操作只需通過wx.authorize() 介面便可以完成,以下是文件中對授權操作的描述:

提前向用戶發起授權請求。呼叫後會立刻彈窗詢問使用者是否同意授權小程式使用某項功能或獲取使用者的某些資料,但不會實際呼叫對應介面。如果使用者之前已經同意授權,則不會出現彈窗,直接返回成功。


也就是說,授權過程實際上只是在小程式前端獲得了操作部分wx 介面的訪問許可,這個過程實際上是不會與開發者伺服器發生任何關係的。那這些訪問許可包含哪些內容呢?再來看微信官方提供的scope 列表:


1.2 登入

所謂的登入就是要讓開發者伺服器知道當前的使用者是誰?在傳統的web 應用中,我們必須要讓使用者輸入賬號和密碼才能實現登入操作。但是在微信應用中,我們可以通過微信伺服器來完成這個操作,獲取到與當前使用者對應的唯一標誌(openId),具體操作實現流程如下:

注:每個使用者相對於每個微信應用(公眾號或者小程式)的openId 是唯一的,也就是說一個使用者相對於不同的微信應用會存在不同的openId


從上圖中,我們可以看出,小程式中登入步驟如下:

① 小程式前端使用wx.login() 從微信伺服器獲取code

② 小程式前端將code 傳送給開發者伺服器,開發者伺服器利用appId、appSecret 和code 向微信伺服器換換取使用者openId 和session_key

③ 開發者伺服器自定義登入態並將其與openId 和session_key 關聯起來然後寫session

④ 開發者伺服器將登入態返回給小程式前端,小程式前端使用wx.setStorageSync() 將登入態儲存起來

⑤ 小程式前端在執行業務請求時將登入態傳送給開發者伺服器,以便開發者伺服器知道當前操作的使用者是哪位。

也就是說,在整個過程中小程式前端是拿不到使用者openId 的,它只能通過開發者伺服器發給它的登入態來告訴伺服器當前使用者的資訊。登入過程中涉及session_key 和unionId,於是又引出了下面的問題。

2. session_key 的作用

那麼,session_key 在登入的過程中或者登入完成後起什麼作用呢?一起來看一下。

2.1 wx.getUserInfo

首先來看一下wx.getUserInfo 這個api:


在設定withCredentials 屬性為true 的情況下,這個api 可以拿到encryptedData,iv 等敏感資訊,encryptedData 需要使用session_key 進行解密,解密後可以拿到的資料如下:


也就是說,session_key 的作用之一是將小程式前端從微信伺服器獲取到的encryptedData 解密出來,獲取到openId 和unionId 等資訊。但是在1.2 登入過程中我們可以看到開發者伺服器是能夠直接拿到使用者的openId 資訊的,而且unionId 也是有其他獲取途徑的,所以session_key 在這裡的作用看起來有點雞肋。

2.2 getPhoneNumber

session_key 更重要的作用大概體現在獲取使用者手機方面(可能還包含其他敏感資訊獲取api)。


從文件中可以看到getPhoneNumber 返回的使用者資料是加密過的,只有使用session_key 才能解密,而小程式前端沒有session_key,所以無法獲取到使用者的手機,只能傳到開發者伺服器進行處理。

3. unionId 的作用,有哪些獲取途徑?

關於unionId 的作用,可以參考Ref 中的連線。簡單來說,就是同一使用者針對同意微信公眾平臺下繫結的所有應用都具有相同的unionId。

獲取途徑有三種,在官方文件中寫的比較清楚:


4. 在應用中如何儲存使用者登入態

儲存使用者登入態,一直以來都有兩種解決方案:前端儲存和後端儲存。

4.1 後端儲存

在1.2 步驟③ 中寫session 的時候可以直接設定過期時間,定期通知小程式前端重新進行登入(wx.login)。

4.2 前端儲存

因為session_key 存在時效性問題(畢竟是用來檢視敏感資訊),而小程式前端可以通過wx.checkSession() 來檢查session_key 是否過期。所以可以通過這個來作為儲存使用者登入態的機制,這也是小程式文件中推薦的方法: