費時一個多月終於使用 Session 實現了二維碼掃碼登錄功能
我終於完成了二維碼掃碼登錄功能,這個功能開發斷斷續續的用了我一個多月的空閒時間,其中 cookie 回寫和 session 同步就佔了 20 多天,開發有多痛苦,完成後就有多喜悅,。
二維碼掃碼登錄是一種常見的無密碼認證方式,它的實現原理非常簡單:第一步在服務器生成一個唯一二維碼 ID 和對應的隨機 token,返回給 Web 網頁並生成二維碼,第二步用戶使用手機 APP 掃描二維碼,然後將用戶信息與二維碼 ID 傳給後端接口,第三步服務器驗證用戶信息和二維碼 ID,通過後建立會話,第四步網頁端通過輪詢檢查登錄狀態,或通過 Websocket 通知網頁。
我使用微信小程序作爲掃碼客戶端,這樣可以將 Web 網頁通過掃碼和小程序 OPENID 綁定起來。我實現的二維碼掃碼原理如下:
當功能開發完成後,使用微信小程序掃碼正常,用戶確認也正常,也可以推送狀態到 Websocket,但是 Web 網頁就是沒有跳轉成功,是 session 認證失敗。通過一番的排查和日誌分析,可以定位到小程序使用的 session 和 Web 網頁的 session 不是同一個,也就是說,當網頁去檢查 session 狀態時還是未登錄,現在也就是如何實現 session 同步,網上給出的方法試了很多,都沒有生效。而 gin sessions 又不支持通過 sessionID 查找 session,這個問題調試了好多天都沒有解決,都差點要放棄,然後計劃使用 jwt token 來重新實現,網上的好多內容介紹使用 token 來實現。在排查問題時,知道我的思路是沒有問題的。
我只能自己給自己打氣,要相信自己是可以完成的。我接下來要做的功能,就是錄音上傳內容,然後通過豆子工具中的智能語音電話播放,自己聽給自己鼓勵,這個功能是我開發網頁端的初衷,過年之後就在計劃,由於小程序對於用戶上傳內容審覈嚴格,通過 Web 網頁實現,然後通過小程序掃碼綁定小程序用戶。錄音用來自己聽,或者分享給他人聽,錄音的詳細內容等後續完成了錄音上傳模塊再寫文章介紹。沒得辦法,只能去啃原理和概念,花了幾天時間,看 token、session 概念,看 Golang gin sessions 的源代碼,一點點排查問題,終於克服了。
我來回顧總結一下,首先,HTTP 是一種無狀態協議,爲了識別和記錄用戶,有了 cookie 技術,通過在瀏覽器添加 cookie 來識別用戶,cookie 是由服務器發送到瀏覽器並保存在瀏覽器本地的小型文本數據(通常不超過 4KB),當瀏覽器發送後續請求時,會自動攜帶 cookie,從而實現狀態管理。由於 cookie 存儲太小,以及安全等多種原因,又有了 session 技術,session 是服務器用來跟蹤用戶狀態的一種機制,服務器使用 session 來存儲和跟蹤用戶的狀態信息,通過 cookie 來保存 sessionID,當瀏覽器禁用 cookie 時,又可以通過 URL 重寫來識別用戶狀態,例如將 sessionID 附加在 URL 後(如 example.com?sessionid=123),還有的將 sessionID 放在表單的隱藏 Inpupt 中。我根據自己的實際情況選擇了 cookie 和 session,特別適合我的單機小系統。如果多臺服務器跨域等推薦使用 Token 解決方案。
我的實際情況,剛開始使用 cookie 作爲後端存儲進行調試,無法查看 session 內容,修改 session 存儲後端,將 gin sessions 使用 Redis 作爲後端存儲,通過 Redis 查看 session 是否生成及內容,然後查看 Web 網頁有沒有我創建的 cookie,如果沒有需要設置數據並保存纔可以生成,例如這樣操作可以生成 Web 網頁 cookie。
s := sessions.Default(c)
if s.ID() == "" {
s.Set("tool", true)
if err := s.Save(); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "session init failed"})
return
}
}
打日誌查看 sessionID,二維碼生成接口打印 sessionID,用戶掃碼確認接口打印 sessionID,發現 sessionID 不一樣,而 cookie 中存放的是 sessionID 加密後的內容,所以 Web 網頁不會認證成功。現在是解決如何 session 同步,或者用戶確認接口使用 Web 網頁的 session,先將兩個接口都劃到了同一個域名下,解決跨域問題,由於小程序端不會自動攜帶 cookie,所以後端 gin sessions 會生成一個新的 sessionID,現在 Websocket 和生成二維碼都是 Web 網頁端發起,可以在 Websocket 接口協議升級前獲取 session,然後在消息處理邏輯中保存認證消息到會話中。認證消息可以在當用戶掃碼並確認後,通過 Redis 轉發用戶信息給 Websocket,Websocket 取出用戶信息然後使用 session 在會話中寫入認證信息。成功之後發消息通知 Web 網頁,Web 網頁調用 check session 接口刷新 cookie 並根據返回接口選擇跳轉到面板頁面,或者讓用戶重新登錄,這樣就完成了二維碼掃碼登錄。
很多零碎的問題,只記錄了最主要的問題,通過開發二維碼掃碼登錄,對 gin session 的瞭解又深入了很多。
Web 網頁演示地址:
https://tool.91demo.top
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/MWV58-JBp9Z7rd9_by6z3g