單頁面應用在微信服務號下的登錄流程


最近我們的小程序涉及到虛擬支付的問題,在ios端的支付被封掉了😇,所以有了在服務號上搞一套H5版的小程序的需求。由於我們小程序是mpvue寫的,為了盡量復用之前的樣式和邏輯,選擇了前后端分離的模式,於是一段新的踩坑之旅開始了。放下wx的jssdk暫且不表,今天來說說登錄時遇到的坑。

服務號的登錄流程

以前搞過服務號的同學對於它的登錄流程應該不陌生,就是當后端檢測到當前用戶沒有授權時,將會重定向到微信的授權頁面,當用戶點擊這個授權的button時,微信會根據Url查詢字符串中的重定向URL,重新回到我們的頁面。

下面3幅圖展示了整個過程:

  1. 當我們的服務器發現用戶沒有授權,返回302狀態碼,以及微信的授權頁面location

    1.png

  2. 用戶在該頁面點擊確認登錄

    uploading-image-28683.png

  3. 微信服務器根據location里的redirectURL,返回301code,重定向回來

    2.png

上面三步,經歷了兩次重定向,第一次從自己的服務器重定向到微信的服務器,微信展示授權頁面。第二次重定向是當用戶點擊之后,微信會帶一個code重定向回來,當服務器拿到這個code之后,經歷一波獲取openId的操作之后,生成一個session,這樣用戶以后訪問時就不需要再次登錄。

這樣的模式在傳統的前后端不分離,基於模板的情況下,是沒有問題的,因為沒有json的返回,后端進行邏輯處理后,渲染出html。但是在單頁面的情況下,如果思路跑偏會出現一堆問題。

單頁面遇到的問題

上面說的思路跑偏是什么意思呢?就是當用戶進來時,先將單頁面的index.html發給瀏覽器。當瀏覽器執行開始js腳本(app.js)時,就會向服務器發送請求。

此時如果是一個新用戶在訪問,由於沒有登錄,服務器會返回一個302的重定向狀態碼,然而這次請求是通過ajax發起的。瀏覽器不會自動重定向到授權頁面,導致請求失敗。

此時你會想,瀏覽器不會重定向,我可以當請求失敗時通過設置window.location自己重定向到微信授權頁面,這樣解決了第一步的重定向問題,然后當用戶點擊確定登錄時,馬上又面臨第二個重定向的問題--重定向到哪里。

由於微信重定向的url是帶着code返回的,重定向的Url肯定不能是一個靜態頁面的Url,必須是一個api,假設還是login。后端在請求中拿到code之后,生成一個新的session,再將原先的html再次返回給瀏覽器,並帶上set-cookie字段,此后瀏覽器會帶着cookie請求,登錄至此完成。

這樣做ok,但是卻留下一個很恐怖的URL:https://example.com/login?code=001QLbSQ0Ujc162Sp5UQ0IG6SQ0QLbSD,此后前端路由開始work,就在前面的基礎上加上一個#號,如果你的業務還涉及支付,那就完蛋了,因為支付需要配置的url應該是穩定的而code這個查詢參數是動態變的。

解決方案

我畫了一張圖解釋了重新設計的登錄流程:

uploading-image-511687.png

在這個新的流程中,當新用戶第一次發起請求(login)時,不會返html給瀏覽器,只會進行重定向:

  • 如果用戶未登錄,重定向到微信的授權頁,並設置redirect url,使用戶點擊授權后可以重定向回來

  • 新用戶重定向回來之后,login api拿到code,經過生成session操作后,再次重定向到homeurl下

  • 如果是老用戶,直接重定向到homeurl下

  • 此時由於訪問home的用戶都是已登錄狀態,api統一返回index.html,所以最終用戶看到的是https://example.com/home下的頁面,后面的單頁面路由會在這個url下展開。(雖然對服務號用戶來說可能沒什么區別)

總結一下這么做的好處:

  1. 少傳輸一次html頁面,第一種方式一開始就給未登錄的用戶傳html是沒用的

  2. 美觀的url(用戶感知不到)

  3. 前端無需手動重定向,后端將顯示頁面和登錄邏輯放到兩個api中,邏輯更清晰

總結

了解到3xx狀態碼的博大精深,盡管對普通用戶感知不深,沒有2xx受群眾歡迎,也沒有404,500知名度高,屬於默默無聞型的。但是在互聯網世界里卻扮演着重要的角色。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM