vue實現微信網頁授權登錄

附:微信官方文檔

前言:在用vue做微信公衆號網頁項目的授權登錄中踩過不少坑,在這裏記錄一下。首先在選擇由後端做登陸還是前端傳token登錄的方式上產生了分歧。兩種方式在不同的公司裏都用過,後端做登陸無非是前端跳轉到jsp或者php頁面,後端把登錄做了在跳轉回頁面,這種方式前端方便了,但是中途需要跳轉多次,很影響體驗,所以最終選擇了前端傳token的方法進行登錄。

不想看過程的可以直接往下拉查看完整代碼

目錄

一、授權流程

二、完整代碼

一、授權流程

由微信的官方文檔得知,授權登陸共分爲四步:

其中,第一步由前端來做,第二步前端通過ajax把code傳到後端,後端獲取access_token,第三步第四步則需要後端完成。

寫代碼之前需要明確下需求,整理下思路,先想在寫是個好習慣。

我們需要做的是:

1、前端在需要獲取用戶信息的頁面調起登錄,某些頁面不需要,比如首頁、某些展示靜態頁。

2、微信返回,前端截取返回url中的code傳給後臺,並把後臺返回的token存到session和axios的header頭中。

3、如果session中已經有token了,調另一個接口,判斷token是否已經過期,過期重新登陸。

開始寫代碼。

因爲單頁面應用的url帶着#,微信授權登陸回調對#支持不友好,所以我們把路由換成history模式,後臺配合改一下,不然頁面會404。

mode: "history"

在路由守衛的beforeEach中寫登錄代碼

首先登錄,1:

window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri=" + redirect_uri + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"

白名單判斷:

let noLoginArr = ["/"], isCur = false
for (let i of noLoginArr) {
    if (to.path == i) {
        isCur = true
    }
}
if (isCur) { //白名單內不做登錄判斷,直接next
    next()
} 

登陸之後截取url中的code傳給後臺,2:

let data = {
    code: code
}
axios.post('/api/auth/code', data).then((res) => {
    if (res.code == 200) {
        sessionStorage.setItem("token", res.data.token)
        axios.defaults.headers.common['token'] = res.data.token
        next()
    } else if (res.code == 401) { //後臺判斷toke是否失效,失效返回401重新授權登陸
        //去登錄
        window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri=" + redirect_uri + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"
    }
}).catch(function (error) {
});

如果session中有token,3:

axios.defaults.headers.common['token'] = sessionStorage.getItem("token")
let data = {
    token: token
}
axios.post('/api/auth/checkToken', data).then((res) => { //判斷token是否過期接口
    if (res.code == 200) {
        next()
    } else if (res.code == 401) { //後臺判斷toke是否過期,過期返回401重新授權登陸
        sessionStorage.setItem("token","")
        axios.defaults.headers.common['token'] = ""
        //去登錄
        window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri=" + redirect_uri + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"
    }
}).catch(function (error) {
});

說一下自己踩得一個坑:登陸之後,在當前頁面不動等token過期,刷新頁面。此時頁面會不停的跳轉

解決方案:每次登錄時,去除回調url中的code和state,所以大家在頁面間傳值的時候不要使用code和state關鍵詞。

二、完整代碼

以下是完整代碼:

const routes =[
 // 你的路由
]
const router = new VueRouter({
    mode: "history",
    routes
})

function delCodeandstate(to) { //函數作用:去除url中的code和state
    let path = ""
    for (let i in to.query) {
        if (i != "code" && i != "state") {
            path = path + "&" + i + "=" + to.query[i]
        }
    }
    path = path == "" ? "" : path.substring(1, path.length)
    path = path == "" ? "" : "/?" + path
    return path;
}

router.beforeEach((to, from, next) => {
    let fullPath = to.fullPath
    if (to.fullPath.includes("code")) { //判斷url中是否有code,踩坑1-頁面反覆跳轉
        fullPath = delCodeandstate(to)
    }
    let redirect_uri = encodeURIComponent(newUtils.getPath().url + fullPath), appid = newUtils.getPath().appid //1、newUtils.getPath()是寫的公共方法,裏面是url和appid等參數。2、redirect_uri,授權登陸後的回調地址,需要進行encodeURIComponent處理
    let code = to.query.code, state = to.query.state
    let noLoginArr = ["/"], isCur = false, token = sessionStorage.getItem("token") //noLoginArr,白名單,不需要授權登陸的頁面
    for (let i of noLoginArr) {
        if (to.path == i) {
            isCur = true
        }
    }
    if (isCur) { //白名單內不做登錄判斷,直接next
        next()
    } else {
        if (code && state && !token) { //登陸之後獲取到code,傳到後臺登錄
            let data = {
                code: code
            }
            axios.post('/api/auth/code', data).then((res) => {
                if (res.code == 200) {
                    sessionStorage.setItem("token", res.data.token)
                    axios.defaults.headers.common['token'] = res.data.token
                    next()
                } else if (res.code == 401) { //後臺判斷toke是否失效,失效返回401重新授權登陸
                    //去登錄
                    window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri=" + redirect_uri + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"
                }
            }).catch(function (error) {
            });
        } else if (token) { //已登錄,有token,判斷是否過期
            axios.defaults.headers.common['token'] = sessionStorage.getItem("token")
            let data = {
                token: token
            }
            axios.post('/api/auth/checkToken', data).then((res) => { //判斷token是否過期接口
                if (res.code == 200) {
                    next()
                } else if (res.code == 401) { //後臺判斷toke是否過期,過期返回401重新授權登陸
                    sessionStorage.setItem("token","")
                    axios.defaults.headers.common['token'] = ""
                    //去登錄
                    window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri=" + redirect_uri + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"
                }
            }).catch(function (error) {
            });
        } else { //未登錄,沒有token,去登錄
            //去登錄
            window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri=" + redirect_uri + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"
        }
    }
})
export default router

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章