附:微信官方文档
前言:在用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..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..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..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("http://xxx.com" + fullPath), appid = "你的小程序appid" //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..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..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..com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri=" + redirect_uri + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect" } } }) export default router
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/218806.html原文链接:https://javaforall.net
