vue微信授权解决方案

之前是自己太年轻,写什么【最终解决方案】。这一次的项目vue移动端电商项目,做了很多的优化。大家都知道授权需要每次都要发布到线上,本地的需要代理,这让我们很头疼。后面会介绍一个本地直接授权的方式,真的超级香。时隔几年,第三次升级我的微信授权,每一次思路都更加清晰,当我的知识越来越广,越来越深,我相信会有第四次,第五次。。。另外也优化:微信分享keep-alive返回到上次浏览的位置vue-router 所有页面携带参数…后续会持续分享,接下来首先优化的就是授权逻辑的优化。场景整个项目无论什么页面进入都需要进行授权,一般微信公众号H5项目这一点都是需要做到接下来我们开始吧,先克隆安装依赖,不要着急启动,先把准备工作做好。// 克隆项目
git clone https://github.com/sunnie1992/vue-wechat-auth.git
//安装依赖
npm install 复制代码实现本地微信授权1.工具实现本地开发授权,你需要使用微信开发者工具,网页是没有办法直接本地拿到授权的。2.将auth.html部署到服务器上这里我们用到了 GetWeixinCode ,使用的时候修复了一些bug携带的参数在授权完之后没能全部带回来。hash回调url错误问题部署auth.html(在github项目的根目录下)到你的微信授权回调域名的目录下。前往微信公众平台->接口权限->网页授权获取用户基本信息->修改,填写授权回调页面域名,例如www.abc.com在www.abc.com域名下部署auth.html,不一定是根目录,例如:https://www.abc.com/xxx/auth.html 微信登录 复制代码3.实现代码逻辑主要文件:src/plugins/wechatAuth.js微信授权相关方法封装这里引用的是[vue-wechat-login],做了简单的修改,直接在路由钩子文件permission.js使用。const qs = require(‘qs’)// 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)const SCOPES = [‘snsapi_base’, ‘snsapi_userinfo’]class VueWechatAuthPlugin { constructor() { this.appid = null this.redirect_uri = null this.scope = SCOPES[1] this._code = null this._redirect_uri = null } static makeState() { return ( Math.random() .toString(36) .substring(2, 15) + Math.random() .toString(36) .substring(2, 15) ) } setAppId(appid) { this.appid = appid } set redirect_uri(redirect_uri) { this._redirect_uri = encodeURIComponent(redirect_uri) } get redirect_uri() { return this._redirect_uri } get state() { return localStorage.getItem(‘wechat_auth:state’) } set state(state) { localStorage.setItem(‘wechat_auth:state’, state) } get authUrl() { if (this.appid === null) { throw new Error(‘appid must not be null’) } if (this.redirect_uri === null) { throw new Error(‘redirect uri must not be null’) } this.state = VueWechatAuthPlugin.makeState() return https://open.weixin.qq.com/connect/oauth2/authorize?appid=${this.appid}&redirect_uri=${this.redirect_uri}&response_type=code&scope=${this.scope}&state=${this.state}#wechat_redirect } returnFromWechat(redirect_uri) { const parsedUrl = qs.parse(redirect_uri.split(’?’)[1]) if (process.env.NODE_ENV === ‘development’) { this.state = null this._code = parsedUrl.code } else { if (this.state === null) { throw new Error(“You did’t set state”) } if (parsedUrl.state === this.state) { this.state = null this._code = parsedUrl.code } else { this.state = null throw new Error(Wrong state: ${parsedUrl.state}) } } } get code() { if (this._code === null) { throw new Error(‘Not get the code from wechat server!’) } const code = this._code this._code = null // console.log(‘code: ’ + code) return code }}const vueWechatAuthPlugin = new VueWechatAuthPlugin()export default vueWechatAuthPlugin复制代码4.设置相关变量在开发之前你要首先在下面三个文件设置两个变量,如果你已经启动项目,设置后需要重启。.env.development .env.staging .env.productionVUE_APP_WECHAT_APPID是你的appid,在.env.[环境] 文件中设置VUE_APP_WECHAT_AUTH_URL是你的auth.html 访问地址。在.env.[环境] 文件中设置5.permission.js 路由守卫设置授权白名单whiteList,授权失败,或者其他错误进入404页面。 // 设置回调地址,本地和线上不同 wechatAuth.redirect_uri = processUrl() await store.dispatch(‘user/setLoginStatus’, 1)
// 跳转完整的授权地址
window.location.href = wechatAuth.authUrl复制代码wechatAuth.authUrl 地址 https://open.weixin.qq.com/connect/oauth2/authorize…的redirect_uri 设置调用 processUrl方法,本地开发,回调设置本地路径会报redirect_uri错误,所以我们跳到中间页auth.html再携带code跳会到backUrl。本地环境返回授权的回调地址:${process.env.VUE_APP_WECHAT_AUTH_URL}?backUrl=${window.location.href}复制代码 其中 process.env.VUE_APP_WECHAT_AUTH_URL 就是中间授权页面的网址。backUrl后面跟的是你本地开发的地址。https://www.abc.com/auth.html?backUrl=http://localhost:9018/#/线上环境返回的是正常的微信授权地址:https://open.weixin.qq.com/connect/oauth2/authorize…redirect_uri是线上的地址,不用中间页跳转。import qs from ‘qs’import router from ‘@/router’import store from ‘@/store’import wechatAuth from ‘@/plugins/wechatAuth’// 设置APPIDwechatAuth.setAppId(process.env.VUE_APP_WECHAT_APPID)const whiteList = [’/404’]router.beforeEach(async(to, from, next) => { // 在白名单,直接进入 if (whiteList.indexOf(to.path) !== -1) { return next() } const { loginStatus } = store.getters switch (Number(loginStatus)) { case 0: // 获取跳转地址 wechatAuth.redirect_uri = processUrl() await store.dispatch(‘user/setLoginStatus’, 1) window.location.href = wechatAuth.authUrl break case 1: try { wechatAuth.returnFromWechat(to.fullPath) const code = wechatAuth.code await store.dispatch(‘user/loginWechatAuth’, code) await store.dispatch(‘user/setLoginStatus’, 2) next() } catch (err) { await store.dispatch(‘user/setLoginStatus’, 0) next(’/404’) } break case 2: next() break default: break }}) /** * 处理url链接 * @returns {string} */function processUrl() { // 本地环境换通过auth.html拿code if (process.env.NODE_ENV === ‘development’) { // 中间授权页地址 return ${process.env.VUE_APP_WECHAT_AUTH_URL}?backUrl=${window.location.href} } const url = window.location.href // 解决多次登录url添加重复的code与state问题 const urlParams = qs.parse(url.split(’?’)[1]) let redirectUrl = url if (urlParams.code && urlParams.state) { delete urlParams.code delete urlParams.state const query = qs.stringify(urlParams) if (query.length) { redirectUrl = ${url.split('?')[0]}?${query} } else { redirectUrl = ${url.split('?')[0]} } } return redirectUrl}复制代码当配置好参数,本地启动后,可以正常进入授权页面// 启动
npm run serve 复制代码同意之后就看到code值了到此主要的流程就结束了。当授权成功后需要通过code换取token,因为并没有对接后台,所以这里我注释掉了接下来操作在vuex中进行,用户根据需求对接后台接口即可。/src/store/modules/user.jsimport {loginByCode} from '@/api/user’import { saveToken, saveLoginStatus, saveUserInfo, removeToken, removeUserInfo, removeLoginStatus, loadLoginStatus, loadToken, loadUserInfo} from '@/utils/cache’const state = { loginStatus: loadLoginStatus(), // 登录状态 token: loadToken(), // token userInfo: loadUserInfo() // 用户登录信息}const mutations = { SET_USERINFO: (state, userInfo) => { state.userInfo = userInfo }, SET_LOGIN_STATUS: (state, loginStatus) => { state.loginStatus = loginStatus }, SET_TOKEN: (state, token) => { state.token = token }}const actions = { // 登录相关,通过code获取token和用户信息,用户根据自己的需求对接后台 loginWechatAuth({commit}, code) { const data = { code: code } return new Promise((resolve, reject) => { loginByCode(data) .then(res => { // 存用户信息,token commit(‘SET_USERINFO’, saveUserInfo(res.data.user)) commit(‘SET_TOKEN’, saveToken(res.data.token)) resolve(res) }) .catch(error => { reject(error) }) }) }, // 设置状态 setLoginStatus({commit}, query) { if (query === 0 || query === 1) { // 上线打开注释,本地调试注释掉,保持信息最新 removeToken() removeUserInfo() } // 设置不同的登录状态 commit(‘SET_LOGIN_STATUS’, saveLoginStatus(query)) }, // 登出 fedLogOut() { // 删除token,用户信息,登陆状态 removeToken() removeUserInfo() removeLoginStatus() }}export default { namespaced: true, state, mutations, actions}复制代码utils/cache.js文件用户来缓存数据import cookies from 'js-cookie’import storage from 'good-storage’const LoginStatusKey = ‘Login-Status’ // 登录态 0未授权未登录 1授权未登录 2 登陆成功const TokenKey = ‘Access-Token’ // tokenconst UserInfoKey = ‘User-Info’ // 用户信息 {} {…}// 获取登录状态export function loadLoginStatus() { return cookies.get(LoginStatusKey) || 0}// 保持登录状态export function saveLoginStatus(status) { cookies.set(LoginStatusKey, status, {expires: 7}) return status}// 删除登录状态export function removeLoginStatus() { cookies.remove(LoginStatusKey) return ‘’}// 获取tokenexport function loadToken() { return storage.get(TokenKey, ‘’)}// 保存tokenexport function saveToken(token) { storage.set(TokenKey, token) return token}// 删除tokenexport function removeToken() { storage.remove(TokenKey) return ‘’}// 获取用户信息export function loadUserInfo() { return storage.get(UserInfoKey, {})}// 保存用户信息export function saveUserInfo(userInfo) { storage.set(UserInfoKey, userInfo) return userInfo}// 删除用户信息export function removeUserInfo() { storage.remove(UserInfoKey) return {}}复制代码项目地址github:vue-wechat-auth另外,项目架构介绍请看[ vue-h5-template]基于vue-cli4.0+webpack 4+vant ui + sass+ rem适配方案+axios封装。如果你只需要授权逻辑,只要把涉及到的相关文件放到你的项目下就可以。

发布了70 篇原创文章 · 获赞 10 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/a59612/article/details/104463969