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

猜你喜欢

转载自blog.csdn.net/yuyuking/article/details/103891198