單頁面應用在微信服務號下的登錄流程
最近我們的小程序涉及到虛擬支付的問題,在ios端的支付被封掉了??,所以有了在服務號上搞一套H5版的小程序的需求。由於我們小程序是mpvue寫的,為了盡量復用之前的樣式和邏輯,選擇了前後端分離的模式,於是一段新的踩坑之旅開始了。放下wx的jssdk暫且不表,今天來說說登錄時遇到的坑。
服務號的登錄流程
以前搞過服務號的同學對於它的登錄流程應該不陌生,就是當後端檢測到當前用戶沒有授權時,將會重定向到微信的授權頁面,當用戶點擊這個授權的button時,微信會根據Url查詢字符串中的重定向URL,重新回到我們的頁面。
下面3幅圖展示了整個過程:
當我們的服務器發現用戶沒有授權,返回
302
狀態碼,以及微信的授權頁面location用戶在該頁面點擊確認登錄
微信服務器根據location裏的redirectURL,返回
301
code,重定向回來
上面三步,經歷了兩次重定向,第一次從自己的服務器重定向到微信的服務器,微信展示授權頁面。第二次重定向是當用戶點擊之後,微信會帶一個code重定向回來,當服務器拿到這個code之後,經歷一波獲取openId的操作之後,生成一個session,這樣用戶以後訪問時就不需要再次登錄。
這樣的模式在傳統的前後端不分離,基於模板的情況下,是沒有問題的,因為沒有json的返回,後端進行邏輯處理後,渲染出html。但是在單頁面的情況下,如果思路跑偏會出現一堆問題。
單頁面遇到的問題
上面說的思路跑偏是什麽意思呢?就是當用戶進來時,先將單頁面的index.html
此時如果是一個新用戶在訪問,由於沒有登錄,服務器會返回一個302的重定向狀態碼,然而這次請求是通過ajax發起的。瀏覽器不會自動重定向到授權頁面,導致請求失敗。
此時你會想,瀏覽器不會重定向,我可以當請求失敗時通過設置window.location
自己重定向到微信授權頁面,這樣解決了第一步的重定向問題,然後當用戶點擊確定登錄時,馬上又面臨第二個重定向的問題--重定向到哪裏。
由於微信重定向的url是帶著code返回的,重定向的Url肯定不能是一個靜態頁面的Url,必須是一個api,假設還是login。後端在請求中拿到code之後,生成一個新的session,再將原先的html再次返回給瀏覽器,並帶上set-cookie
這樣做ok,當時卻留下一個很恐怖的URL:https://example.com/login?code=001QLbSQ0Ujc162Sp5UQ0IG6SQ0QLbSD
,此後前端路由開始work,就在前面的基礎上加上一個#
號,如果你的業務還涉及支付,那就完蛋了,因為支付需要配置的url應該是穩定的而code這個查詢參數是動態變的。
解決方案
我畫了一張圖解釋了重新設計的登錄流程:
在這個新的流程中,當新用戶第一次發起請求(login)時,不會返html給瀏覽器,只會進行重定向:
如果用戶未登錄,重定向到微信的授權頁,並設置redirect url,使用戶點擊授權後可以重定向回來
新用戶重定向回來之後,login api拿到code,經過生成session操作後,再次重定向到
home
url下如果是老用戶,直接重定向到
home
url下此時由於訪問
home
的用戶都是已登錄狀態,api統一返回index.html,所以最終用戶看到的是https://example.com/home
下的頁面,後面的單頁面路由會在這個url下展開。(雖然對服務號用戶來說可能沒什麽區別)
總結一下這麽做的好處:
少傳輸一次html頁面,第一種方式一開始就給未登錄的用戶傳html是沒用的
美觀的url(用戶感知不到)
前端無需手動重定向,後端將顯示頁面和登錄邏輯放到兩個api中,邏輯更清晰
總結
了解到3xx
狀態碼的博大精深,盡管對普通用戶感知不深,沒有2xx
受群眾歡迎,也沒有404
,500
知名度高,屬於默默無聞型的。但是在互聯網世界裏卻扮演著重要的角色。
單頁面應用在微信服務號下的登錄流程