基於一個好玩兒的聊天室理解小程序 session 管理

panda-chat-room

小程序版 websocket 聊天室。 從服務器到小程序客戶端配置基礎教程。html

在本教程內咱們將在小程序內實現一個基本的 websocket 聊天室, 計劃實現如下功能:html5

  1. 微信用戶登陸「 小程序 session 管理 」☑️
  2. 用戶間文本交流 「 websocket 實現 」☑️
  3. 用戶間發送圖片等富媒體信息 「 文件的儲存及相關邏輯 」☑️

熊貓聊天室
圖片描述


小程序已掛,緣由是我的開發者沒法提交信息交流類小程序, 不過在本地運行 demo 仍是沒問題的。node

寫的有紕漏的地方還請你們指出,在 SF 下留言或在 本項目 git 內提 issue ,咱們一塊兒進步 ^o^

聊天室基礎配置

小程序端的聊天室信息流其實很是簡單, 而本教程就藉助一個好玩兒的小程序聊天室來進一步理解小程序中的 session 實現。 git

我在服務器端環境搭建及配置主要參考騰訊雲實驗 基於 CentOS 搭建微信小程序服務github

咱們在此先要理解小程序端爲什麼沒法實現 session, 以及如何在小程序實現 websocket 通訊。web

小程序並不是嵌套在微信內的 html5 網頁, 它並非從 url 訪問到的。 咱們只能本身實現相似會話的東西, 好在官方已經提供了相應的套件來實現 session。 即 wafer-client-sdk 和 node 中間件 wafer-node-session, 咱們依照文檔就能簡單地實現 session。算法

騰訊雲 wafer 項目下有不少類似項目「大部分須要配合騰訊雲進行一鍵部署」, 若是咱們只須要實現小程序 session 管理的話, wafer-client-sdk 和 node 中間件 wafer-node-session 便可。

在服務器端咱們使用了 ws 包來實現 websocket ,沒有使用 socket.io 的緣由是 socket.io 須要客戶端有額外的腳本才能實現通訊。npm

在小程序端咱們引入 wafer-client-sdk 套件使服務器能夠獲取 session。小程序

主要邏輯分爲幾個簡單函數, 固然你須要先配置請求的服務器域名和小程序帳號密碼。微信小程序

// 引入 session 套件, 裏面封裝了 wx.login, wx.getUserInfo 等操做
const wafer = require('../../vendors/wafer-client-sdk/index')

// 用於登陸使服務器得到 session, 而後服務器返回的 session 裏就會包含用戶信息了, 用來在 websocket 裏返回發信息用戶的頭像 url
function login(){
  .....
}

// 用於有新信息時更新數據, msg 指信息, ad 指 websocket 傳回的信息 id, 用於 scroll-into-view 滾動
pushMsg(msg, ad) {
  .....
}

// 用於監聽 websocket 鏈接
listen(){
  .....
}

//  用於小程序發送 websocket 信息
send(){
  .....
}

基本就是這些, 關於 websocket 通訊過程是這樣的:

  1. 客戶端發送信息給服務器 m1
  2. 服務器收到信息後根據條件返回給客戶端 m2
  3. 每一個客戶端收到 m2 後更新視圖

固然最開始是要與服務器端 websocket 鏈接的, 只有每一個鏈接了的客戶端才能夠交流信息。

小程序 session 解析

對於 session 的實現咱們在服務器端使用了 wafer-node-session 即爲鏈接提供 session 能力。 在小程序端咱們配套使用了 wafer-client-sdk, 這裏面封裝了 wx.request、 wx.login 等邏輯, 實現了小程序端的用戶登陸、session 設置。

關於小程序端的 session 獲取問題主要有以下幾個步驟

  1. wx.login 獲取 code
  2. wx.request 發送 code 給本身的服務器
  3. 服務器收到 code 配合 appId 和 appSecret 發送給微信服務器換取 openId 和 sessionKey
  4. wx.getUserInfo 會獲得 rawData、signature、encryptedData、 iv, 咱們須要把它們發送到本身服務器。 咱們構建本身的 signature2 = sha1(sessionKey + rawData) , 比對 signature 和 signature2 就完成了數據校驗
  5. 服務端經過 aes-128-cbc 算法對稱解密 encryptedData 和 iv 而後獲得 userInfo 此次獲得的 userInfo 裏還包含 openId 等信息 「若是在微信開放平臺綁定小程序就會獲得 unionId」
  6. 服務端構建 req.session 對象並返回給小程序,裏面包含 id、 userInfo、 sessionKey「小程序傳到服務器的」、skey 「服務器本身根據sessionKey + appId + appSecret 生成, 有過時時間」。 而咱們本身生成的 skey 是有設置過時時間的, 但小程序端的 session 也有本身的過時時間 「應該是微信按使用小程序的頻率來動態設置過時時間的。 wafer 會自動調用 wx.checkSession 檢查是否過時, 過時了就 wx.login」。

在咱們的 demo 中就出現了服務器 session 已通過期而本地 session 還沒過時的狀況。 而 websocket 每次發送信息都須要從 req.session 內獲取用戶頭像, 因此會致使 websocket 鏈接失敗。 可是在小程序端 session 未過時,即在服務器端的 sessionKey 和小程序的 sessionKey 不一致了 「客戶端 sessionKey 還在而服務器的 sessionKey 已通過期銷燬」, 致使比對失敗。 那怎麼辦呢? 從新請求唄! 可是由於 wafer 封裝了 session 管理 「小程序端 session 過時後纔會從新請求」 存在 session 緩存的緣故, 小程序並無從新發送信息給本身的服務器進而生成新的 sessionKey, 因此咱們在每一次 wx.sendSocketMessage 發信息的時候都要檢查服務器端的 session 狀況, 這裏須要作簡單的判斷「websocket 信息有錯誤就清除本地 session」讓小程序從新請求服務器。

websocket 信息發送

既然要發送信息「即產生數據」, 那麼這些信息都儲存在哪裏呢? 在發送文本信息時, 服務器端收到數據後只作簡單地處理便返回給小程序, 這時的數據應該是儲存在服務器內存中。 由於 websocket 在收到請求後簡單處理了字符串信息直接返回給小程序, 那咱們發送其它富媒體信息時,也能夠以二進制的方式發送給 websocket 服務器, 而後從新返回給客戶端 「即 websocket 只作文件中轉」,相關實現 websocket-stream 。 貌似看起來很複雜,在這裏我使用了國內的 paas 服務商 leanCloud 的儲存服務 「即小程序端把發送的文件儲存在雲端,返回一個文件地址」,而後咱們把這個文件信息進行標註「即只發送文件的 url 信息, 小程序端判斷請求是不是文件進而顯示」。 固然你也能夠發送視頻或者音頻, 把他們都保存在雲端, 只發送其相應的 url 便可。 咱們這裏的 websocket 服務器只作一個文件中轉的功能, 而文件的存儲交給雲端來負責。

panda-chat-room 項目源碼

項目源碼 ☑️

相關文章
相關標籤/搜索