Vue微信專案按需授權登入策略實踐

FrankCheung發表於2018-05-06

寫在前面

專案採用Vue作為開發框架,使用者瀏覽頁面時有兩種情況:

  1. 一種是需要使用者先登入之後才能繼續瀏覽;
  2. 另一種是使用者無需登入即可隨意瀏覽。

在無需使用者登入的頁面中,可能包含需要使用者資訊的操作,此時就需要使用者登入之後方能進行後續操作。因此,需要對授權登入策略進行區分。

思路

一般而言,我們為微信開發的H5頁面,進入頁面的時候就進行鑑權,要求使用者登入之後才能繼續瀏覽。但由於產品需求,這個專案我們需要對不同頁面的鑑權策略進行劃分,按照一般與特殊進行設計:

  1. 一般情況,使用者進入頁面第一時間要求使用者授權登入,按照常規的微信授權登入流程,登入之後,使用者繼續瀏覽。
  2. 特殊情況,為無需使用者登入的頁面配置白名單,只要進入存在於白名單的路由,不進入檢測使用者登入狀態的函式,直接渲染頁面。
  3. 對於使用者未登入狀態下進行的需要使用者資訊的操作,按照我目前的理解,即使是基於微信的靜默授權,頁面也必須重新重新整理,無法做到真正無感授權並且繼續使用者的操作。因此我選擇在前端層面給使用者更友好的提示,讓使用者瞭解授權過程,缺點是前一次操作僅僅是觸發授權登陸,授權登入後,使用者需要再次進行操作。
// routerRule.js

export default function routerRule (router, whiteList = []) {
    // other codes...
    
    router.beforeEach( (to, from, next ) => {
        // 因為授權登入涉及非同步操作,因此使用promise,成功的回撥中呼叫next函式
        new Promise((resolve, rejects) => {
            
            if ( whiteListRouter.indexOf(to.path) !== -1 ) {
                resolve()
                return
              }
            
            // 常規頁面授權登入過程
            if (hasToken()) {
                // codes,獲取使用者資訊並且跳轉所需跳轉的頁面
                
            } else {
                // 判斷使用者是否已經進行微信授權
                if (hasAuthed()) {
                    // 進行過微信授權之後,重定向回來的url中包含了微信的授權資訊,可以將url上擷取的引數傳送到伺服器,換取使用者的token,隨後進入上述有token時候的步驟
                    getWechatUserInfo().then(res => {
                        resolve()
                    })
                    
                } else {
                    // 使用者尚未進行微信授權,則呼叫微信授權的方法,進行授權登入。
                    getWechatAuth()
                }
            }
            
        }).then( res => {
            next()
        })
    })
    
    
    router.afterEach(( to, from ) => {
        wxShare({ title: to.meta.title, desc: to.meta.shareDesc, link: to.meta.shareLink, logo: to.meta.shareLogo})
      })
  
}


複製程式碼

本專案是在使用者初次進行微信繫結時,就將使用者的微信資訊與本站的使用者資訊進行的繫結,因此在獲取使用者微信授權資訊後,就可以獲取到使用者的token,從而獲取使用者在本站的其他使用者資訊。

在無需登入頁面的進行需要許可權的操作的處理

根據上面的邏輯,進入白名單之後,整個函式已經被return掉,不會進入下面的鑑權過程。但是如果是在此種頁面上進行需要許可權的操作,那麼就需要觸發授權登入流程,並且在授權之後,要一併獲取使用者資訊。


// checkLogin.js

export function checkLogin({ redirectUrl, wxAuthLoading, wxAuthLoaded, callback } = {}) {
    if (getToken()) {
        // ...
        callback && callback()
    } else {
        // 提示使用者正在授權中
        wxAuthLoading && wxAuthLoading()
        getWechatAuth( redirectUrl || window.location.href ).then( res => {
            // 授權完畢,提示使用者授權成功
            wxAuthLoaded && wxAuthLoaded()
        })
    }
}

複製程式碼

同時,我們需要對路由白名單新增一些操作

// routerRule.js

export default function routerRule (router, whiteList = []) {
    // other codes...
    
    router.beforeEach( (to, from, next ) => {
        // 因為授權登入涉及非同步操作,因此使用promise,成功的回撥中呼叫next函式
        new Promise((resolve, rejects) => {
            
            if ( whiteListRouter.indexOf(to.path) !== -1 ) {
                // 如果已經進行微信授權但是沒有token值的,就呼叫以下函式獲取token值
                if ( !hasToken() && hasAuthed() ) {
                    getWechatUserInfo().then(res => {
                        resolve()
                    })
                }
                resolve()
                return
              }
            
            // 常規頁面授權登入過程
            if (hasToken()) {
                // codes,獲取使用者資訊並且跳轉所需跳轉的頁面
                
            } else {
                // 判斷使用者是否已經進行微信授權
                if (hasAuthed()) {
                    // 進行過微信授權之後,重定向回來的url中包含了微信的授權資訊,可以將url上擷取的引數傳送到伺服器,換取使用者的token,隨後進入上述有token時候的步驟
                    getWechatUserInfo().then(res => {
                        resolve()
                    })
                    
                } else {
                    // 使用者尚未進行微信授權,則呼叫微信授權的方法,進行授權登入。
                    getWechatAuth()
                }
            }
            
        }).then( res => {
            next()
        })
    })
    
    
    // other codes...
  
}


複製程式碼

坑點以及不完善的地方

  1. 這個方案在使用者授權之後,在路由跳轉之前,一定要先獲取使用者資訊,否則在url上的微信授權資訊就會丟失,獲取使用者資訊就會失敗。
  2. 這個方案的缺點在於,需要開發者對在免登陸頁面的所有需許可權操作都加上checkLogin判斷。由於這種需許可權的操作一般都是傳送非同步請求,所以如果不考慮減少不必要的非同步請求的情況下,可以統一在請求的方法上設定攔截器,判斷後端返回的code,如果返回的是使用者未登入的code,就進行微信授權。這種做法開發過程比較方便,但是會在使用者未登入情況下傳送了一些不必要的請求給後端,感覺不太好。

這是本人開發過程中想到的不成熟的方案,如果有更好的方法,請不吝告知,謝謝!

相關文章