基于单页面应用开发了几个微信公众号,梳理下微信公众号网页开发授权流程以便日后查阅。
概述
- 前端框架为vue
- 后端只提供api接口,不涉及任何页面编写
- api通信认证方式为JWT。
- Tips: 前端auth页面可以插播广告
授权流程
SPA微信授权流程图.jpg前端处理
- 前端使用vue-router,在router.beforeEach钩子中对每一个页面(url)做过滤。
- 判断当前请求是否需要登陆,当前用户的登陆状态(即缓存中是否存在token)。缓存使用的
good-storage, vuex
。 - 若需要登陆则缓存当前web_url,并跳转微信授权地址:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
。其中,url参数REDIRECT_URI
为后端callback接口地址。 - router.beforeEach代码
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
// 微信浏览器打开
let ua = window.navigator.userAgent.toLowerCase()
let uaMatch = ua.match(/MicroMessenger/i)
if (!uaMatch || uaMatch[0] !== 'micromessenger') {
alert('请在微信客户端打开')
return false
}
// 未登录的需要保存当前url,跳转到微信授权页面
if (!auth.loggedIn()) {
saveBeforeLoginUrl(to.fullPath)
// 微信授权地址配置在prod.env.js中
window.location.href = process.env.WECHAT_AUTH_URL
return false
}
next()
} else {
next() // 确保一定要调用 next()
}
})
- 路由详情中配置requiresAuth标识是否需要登陆,示例代码如下:
export default new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'Home',
component: Home,
meta: {
title: '首页'
}
}, {
path: '/user',
name: 'User',
component: User,
meta: {
title: '用户中心',
// requiresAuth设置为true时,需要登陆
requiresAuth: true
}
}
]
})
- 后端callback接口完成业务逻辑后,会重定向到前端auth页面。auth页面负责存储token,然后读取本地缓存的web_url,并跳转到web_url。auth页面代码:
<script>
import { mapMutations } from 'vuex'
import { getBeforeLoginUrl, saveBeforeLoginUrl } from 'common/cache'
export default {
name: 'Storage',
data () {
return {
token: this.$route.query.token
}
},
methods: {
...mapMutations(['changeUserToken'])
},
mounted () {
if (!this.token) {
alert('token参数为空')
return
}
// 缓存token
this.changeUserToken(this.token)
// 页面恢复(进入用户一开始请求的页面)
let url = getBeforeLoginUrl()
// 缓存url恢复为默认的首页
saveBeforeLoginUrl('/')
// 此处或背景图可以插播一段广告 ~~~
setTimeout(() => {
this.$router.push({path: url})
}, 1000)
}
}
</script>
后端处理
- 微信授权服务器回调后端的callback接口,携带参数code
- 后端callback接口获取code后,请求以下链接获取网页授权access_token:
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
, 接口返回值:
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE"
}
- 通过openid查询/写入数据库,得到数据库user信息。
- 使用JWT规则生成token,重定向到前端的auth页面。
网友评论