Vue 移动端 hash模式下微信授权登录

需求分析:

1.移动端微信公众号项目,需要获取微信授权进行登录
2.默认打开首页,在路由进入之前进行判断,有如下三种情况
3.本项目有两种账号类型:商家、企业,需在登录页进行选择

  • 未授权过,跳到微信授权登录页,然后再跳到登录页
  • 有授权过,并且本地有登录的用户信息,跳到首页
  • 有授权过,但本地没有登录的用户信息,跳到登录页

我遇到问题的一些相关知识点:

1.路由模式:hash

  • 因为hash模式下,url是带#的,微信授权登录时候的 redirect_uri 这里跳转后需要处理下。

2.router.beforeEach:进入路由之前执行,一般用来做一些进入页面的限制。

  • 开发过程中,这里遇到了死循环的情况。
  • 是否对路由进行前置守卫的判断条件问题

3.微信授权登录

4.localStorage 和sessionStorage的问题

  • 因为使用环境是微信浏览器,当关闭页面后,sessionStorage存储的数据会被清除掉,localStorage只有手动清除缓存时才会被清除。
  • 我这里是每次打开首页时都判断是否授权登录过,所以存储的数据要一直保存,所以要用localStorage
  • 过程中做过测试,通过微信的设置页点击清除缓存数据按钮,并不能清除掉localStorage的数据,所以测试中涉及到多账号切换的话,可以临时添加一个清除缓存按钮,正式环境再去掉就可以(localStorage.clear()

router文件夹下的 index.js 代码:

import Vue from 'vue'
import Router from 'vue-router'
import store from '@/assets/store'

Vue.use(Router)

const routes =[
{
    path: '/login', 
    name: 'login',      
    component: resolve => require(['@/pages/login'], resolve),
    meta: {
      title: '智能家居',
    },        
  },
  {
    path: '/', 
    name: 'index',      
    component: resolve => require(['@/pages/index'], resolve),
    meta: {
      title: '智能家居',
      requireAuth: true, // 规定需要权限才能进入
    },      
  }, 
]
const router = new Router({
  linkActiveClass: 'active',
  routes
})

router.beforeEach((to, from, next) => { 
  var href = window.location.href;
  let origin = window.location.origin;
  let redirect_uri = encodeURIComponent(origin + '/index.html#/')  // 授权登陆后的回调地址,需要进行encodeURIComponent处理
  let appid = "" // 写自己公众号的appid
  
  let code = to.query.code // 获取路径中的code参数,确认授权后微信会自动跳转到 redirect_uri ,参数code会拼接到地址后边,后续登录我需要这里的code传给后台,code只能用一次
  
  let token = localStorage.getItem("token"),usertype = localStorage.getItem("usertype")
  
  // 这里很重要,因为router.beforeEach 是每次进入路由前都会执行的,微信登录授权后跳转的路径格式如下:https://m.baidu.com/index.html?code=123&state=1#/
  // hash模式下,跳转的url并不会按我们想的那样,把#拼在index.html后边,而是会加在url的参数的最后,所以这里要做一下判断,如果是从微信跳转来的,就直接带着我需要的参数code跳到登录页
  if (href.includes("com/index.html?code")) {  //url包括 com/?code 证明为从微信登录授权跳转回来的 
    window.location.replace(origin + '/index.html#/login?' + location.href.split('?')[1]);//拼接跳转  
  } else {
    if(to.meta.requireAuth) { // 这个很重要,我尝试过直接判断路径是否是首页的方式,结果苹果手机没有问题,安卓手机全部都是死循环一直跳到授权登录页。使用to.meta.requireAuth 这样就正常了。
      if(code&&!token&&!usertype){ // 有code且没有token和角色(已授权未登录)
        localStorage.setItem("code",code) // 保存code,跳到登录页
        next('/login');
      } else if (!code&&token&&usertype) { //已登录,有token
        next();
      } else if(!code&&!token&&!usertype) { //未授权未登录,没有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"
      } 
    } else { // 当不是首页时,直接进入路由
      next();
    }
  }
}) 
export default router


2020.11.4更新

产品需求发生了一点变化,这里记录一下。

之前:项目入口只有一个,即点击公众号的一个菜单进入首页,在首页路由进入前,进行一些列的利用本地存储的数据相关的判断,然后判断要不要获取微信授权登录、要不要跳到登录页等

现在:项目入口改为两个,即公众号的菜单由之前的一个变成了两个:商家/企业,不需要登录页,同一个用户账号类型不可改变。如果已经是商家账号,再点企业的菜单想进入,就会跳到提示页,提示已是商家账号,然后再跳到商家的首页。

过程:开始是在之前的代码基础上改的,利用本地存储来存储账号类型用户id等数据,后来产品测试过程中要频繁测试两个账号,还要清除本地缓存的数据,而且中间问题频出,于是放弃了利用本地存储的方式

最终实现:每次从公众号菜单栏点进去,都进行一次微信授权登录跳到登录页,根据登录接口后台返回的结果判断,如果点击的是第一次登录时的账号类型,就直接跳到首页,如果不是,就跳到提示页。

代码

有改动的 router 文件夹下的 index.js 部分代码
注:

  • 公众号商家入口url: https://m.baidu.com/index.html#/?usertype=1
  • 公众号企业入口url: https://m.baidu.com/index.html#/?usertype=2
router.beforeEach((to, from, next) => { 
  var href = window.location.href;
  let origin = window.location.origin;
  let redirect_uri = encodeURIComponent(origin + '/index.html#/') 
  //redirect_uri,授权登陆后的回调地址,需要进行encodeURIComponent处理
  
  let appid = "" // 公众号的appid
  
  let code = to.query.code, state = to.query.state, usertypes = to.query.usertype
  if(usertypes) { // 判断是按钮点进来的,记录点击类型
    localStorage.setItem("usertypes",usertypes);
    // console.log("是按钮点进来的,设置usertypes缓存")
  }
  if (href.includes("com/index.html?code")) {  //url包括 com/?code 证明为从微信跳转回来的 
    // console.log("从微信授权跳转过来的")
    window.location.replace(origin + '/index.html#/login?' + location.href.split('?')[1]);//拼接跳转  
  } else { 
    if(to.meta.requireAuth) { // 首页
      // console.log("确定是首页")
      if (usertypes) { // 从按钮点进来的
        // console.log("从按钮点进来的");
        //获取授权
        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"
      } else { // 不是从按钮点进来
        next();
      }
    } else { // 其他页面
      next();
    }
  }
}) 

登录页

created(){
        this.code = this.$route.query.code || localStorage.getItem("code");
        if(this.code) {
            localStorage.setItem("code", this.code);
        }
        // console.log("code是" + this.code + "进入了登录页");
        this.getToken();
    },
    methods:{
        getToken() {
            let types = localStorage.getItem('usertypes');
            let code = this.code + '=' + types;
            getToken(code).then((res) => { 
                if(res.data.code == 500) { // 账号类型错误
                    this.$store.dispatch('set_token',res.data.userId); // 获取返回的结果设置缓存
                    this.$router.replace({ // 跳到提示页
                         path: '/tips'   
                    })
                } else if(res.data.code == 0) {  // 登录成功
                    this.$store.dispatch('set_token',res.data.user.userId); // 获取返回的结果设置缓存
                    this.$store.dispatch('set_usertype',res.data.user.type); 
                    this.$router.replace({ 
                        path:'/', 
                    }) 
                } else { 
                    this.$Message.error(res.data.msg); 
                } 
            }) 
        },
    },
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值