VUE等SPA單頁(yè)面應(yīng)用公眾號(hào)授權(quán)登錄和授權(quán)后頁(yè)面返回的方案

以前開發(fā)微信公眾號(hào)授權(quán)登錄都是由后端來(lái)完成,但是最近在開發(fā)單頁(yè)面應(yīng)用時(shí),頁(yè)面路由不走后臺(tái),在網(wǎng)上查找了一些資料,了解了授權(quán)登錄的原理,便自己封裝的一個(gè)前端授權(quán)登錄的模塊。授權(quán)登錄比較順利完成了,但是遇見了授權(quán)完成后返回頁(yè)面的問(wèn)題,由于授權(quán)成功后微信會(huì)跳轉(zhuǎn)到用戶設(shè)置的redirect_uri鏈接,在按返回鍵返回的時(shí)候又會(huì)返回到微信授權(quán)的鏈接,造成了死循環(huán)。所以經(jīng)過(guò)層層怕坑,決心寫下此文章,做個(gè)記錄。

第一步:用戶同意授權(quán),獲取code

我是在收到后臺(tái)返回code值為需要授權(quán)登錄的時(shí)候跳轉(zhuǎn)到登錄頁(yè)面,在登錄頁(yè)面先判斷連接中是否有code,如果沒(méi)有跳轉(zhuǎn)授權(quán)鏈接。
在確保微信公眾賬號(hào)擁有授權(quán)作用域(scope參數(shù))的權(quán)限的前提下(服務(wù)號(hào)獲得高級(jí)接口后,默認(rèn)擁有scope參數(shù)中的snsapi_base和snsapi_userinfo),引導(dǎo)關(guān)注者打開如下頁(yè)面:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
若提示“該鏈接無(wú)法訪問(wèn)”,請(qǐng)檢查參數(shù)是否填寫錯(cuò)誤,是否擁有scope參數(shù)對(duì)應(yīng)的授權(quán)作用域權(quán)限。

以上鏈接中的appid時(shí)申請(qǐng)公眾號(hào)獲得的appid,redirect_uri是用戶授權(quán)登錄成功后需要跳轉(zhuǎn)的鏈接,需要注意的是redirect_uri需要使用 urlEncode 進(jìn)行處理,其他參數(shù)請(qǐng)查看微信官方文檔https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842

第二步:獲取授權(quán)登錄成功跳轉(zhuǎn)鏈接中的code值

可以使用一下函數(shù)獲取鏈接中的所有參數(shù)

function getUrlParams(){
    var url = location.search; //獲取url攜帶的參數(shù)
    var urlParams = new Object();
    if (url.indexOf("?") != -1) {
        var str = url.substr(1);
        var strs = str.split("&");
        for(var i = 0; i < strs.length; i ++) {
            urlParams[strs[i].split("=")[0]]=unescape(strs[i].split("=")[1]);
        }
    }
    return urlParams;
}

getUrlParams().code便是我們需要得到的內(nèi)容

第三步:將code通過(guò)ajax發(fā)送給后臺(tái)獲取后臺(tái)傳遞過(guò)來(lái)的token和其他用戶信息

有了code我們就可以發(fā)送給后臺(tái),后臺(tái)通過(guò)code解析出用戶信息并生成用戶和用戶的token返回給前端,這個(gè)時(shí)候前端需要將token和用戶信息保存下來(lái),我是使用本地存儲(chǔ)保存的token,用vuex來(lái)保存用戶信息。

第四步返回之前的頁(yè)面

因?yàn)樘D(zhuǎn)授權(quán)鏈接之前我是先跳轉(zhuǎn)下一個(gè)專門的登錄頁(yè)面,所按道理說(shuō)應(yīng)該向前返回3個(gè)頁(yè)面,分別為:第一次跳轉(zhuǎn)的登錄頁(yè)面,微信授權(quán)的頁(yè)面,微信授權(quán)成功后跳轉(zhuǎn)的鏈接(這里我配置的是登陸頁(yè)面),故使用 history.go(-3); 返回。這在開發(fā)者工具中每什么問(wèn)題,可以返回之前的頁(yè)面,但是在手機(jī)上卻不行,經(jīng)過(guò)嘗試發(fā)現(xiàn)手機(jī)只需要向前返回兩個(gè)頁(yè)面,但是考慮為了開發(fā)方便或者可能其他的手機(jī)或其他版本的微信需要向前返回3個(gè)頁(yè)面,所又想了一方法不管怎么樣都能返回到之前的頁(yè)面的方法,方法就是在登錄頁(yè)面(第一次跳轉(zhuǎn)的頁(yè)面中判斷是否又存儲(chǔ)的token,有的話就再返回一次),哈哈,機(jī)智,騷操作~~~

總結(jié):
為了方便自己封裝了一個(gè)模塊:

const wxApi = {
    appid:"*****",
    urlencode: function(url){
        url = (url + '').toString();
        return encodeURIComponent(url).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').  
        replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/%20/g, '+');  
    },
    author: function(redirect_uri){
        redirect_uri = this.urlencode(redirect_uri)
        var url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + this.appid + "&redirect_uri=" + redirect_uri + "&response_type=code"  + "&scope=snsapi_userinfo" + "&state=STATE#wechat_redirect";
        window.location.href = url;
    },
    getUrlParams: function(){
        var url = location.search; //獲取url攜帶的參數(shù)
        var urlParams = new Object();
        if (url.indexOf("?") != -1) {
            var str = url.substr(1);
            var strs = str.split("&");
            for(var i = 0; i < strs.length; i ++) {
                urlParams[strs[i].split("=")[0]]=unescape(strs[i].split("=")[1]);
            }
        }
        return urlParams;
    }
}
module.exports = {
    wxApi
}

使用方法:

  1. 引用模塊
import {wxApi} from "../common/wxApi.js"
  1. 判斷本地是否有taoke,有的話返回上一頁(yè)
if(localStorage.getItem('token')){
    history.go(-1);
    return
}
  1. 判斷當(dāng)前頁(yè)的鏈接是否有code值
if(wxApi.getUrlParams().code!=undefined){ //如果獲取到了微信code,則執(zhí)行獲取token的接口,拿到token需要往前返回兩個(gè)頁(yè)面
    this.getToken(wxApi.getUrlParams().code)
    return
}
// 如果沒(méi)有code則跳轉(zhuǎn)到微信的授權(quán)頁(yè)面
const redirect_uri = config.apiDomain + "/login";
wxApi.author(redirect_uri)

總的代碼就是:

import {wxApi} from "../common/wxApi.js"

export default {
    data() {
        return {}
    },
    created(){
        if(localStorage.getItem('token')){
            history.go(-1);
            return
        }
        if(wxApi.getUrlParams().code!=undefined){
            this.getToken(wxApi.getUrlParams().code)
            return
        }
        const redirect_uri = config.apiDomain + "/login";
        wxApi.author(redirect_uri)
    },
    methods: {
        getToken(code){
            this.$ajax.get("", {code}, res => {
                if(res.data.code == 1) {
                    localStorage.setItem("token", res.data.token);
                    history.go(-2);
                }
            })
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容