zoukankan      html  css  js  c++  java
  • vue 微信授权解决方案

    背景

    前后端分离项目 — SpringSocial 绑定与解绑社交账号如微信、QQ
    2018-08-14更新
    时隔四个月第一次更新,因为项目重构有一次接触到了微信授权,思路已经比原来清晰的多了,将重新修改一下整个文章

    场景

    app将商品分享到微信朋友圈或者分享给微信好友,用户点击页面时进行微信授权登陆,获取用户信息。
    问题:没有固定的h5应用首页,回调不能到index。授权后重定向url带参数并且很长

    本人愚钝,开发过程中,尝试过很多方法,踩坑不足以形容我的心情,可以说每一次都是一次跳井的体验啊。

    1.一开始尝试的方式是前端请求微信连接,返回code,然后code作为再去请求后台接口获取token,后面看到别人的博客说这个方法不好,最好就是直接请求后台接口,然后后台返回url做跳转,所以就采用了最传统的方法,后台返回url,前台跳转。

    2.这个时候就出现一个问题,微信授权要跳跳跳,最终想回到第一次点进来时候的链接就蛋疼了,从网上查了一下解决方法,将链接本身作为redirect_uri参数,大概就是这个样子

    
    https://open.weixin.qq.com/connect/oauth2/authorizeappid=xxxxxxxxxxxxxxxxxx&redirect_uri=*www.admin?http://www.xxx.com/h5/product*&response_type=code&scope=snsapi_userinfo&state=STATE&connect_redirect=1#wechat_redirect
    
    

    然而我们的前台链接是这个鬼样子的,本身带参数,而且超长,what?微信可能不会接受我长这么丑。/(ㄒoㄒ)/~~

    
     http://www.xxx.com/h5/product?id=6RedfM5O4xeyl0AmOwmyipkHr8AQCv-hYXZVAIFTwDXOsWSKqgu3VaCmaKSerBnacvWuzO3Zwdf8y%2F2K2lvqkluV6Ane4LCAKyPU2tPAPj%2FMF6F6xkzp27GqqpNya7HbdEA34qGQJvHIA9tlIMkeEWid1112b8oZuP3FQBwU%2F%2FMaSrovzQP6LlzWamyPnv0vMizu8uh0ItpJOQUV1m%2FtemF3U9KuHo8rXCw%3D
    

    最终放弃了这个方案

    3.考虑如何重定向我的前台地址,并且获取token

    接下来就是我现在用的方法,bug还有很多,先分享一下我的方法,后期优化或有更好的方法再做修改
    在main.js中路由全局钩子判断本地是不是有user_token,也就是微信授权后返回的token,如果没有token,并且当前的路由不是author(专门为了授权而生的页面),那就保存当前的url,比如www.xxx.com/h5/product?id=6RedfM5O4xeyl0AmOwm,然后进入author。那如果本地有token,就是用户之前授权拿到过token并且vuex里没有用户信息,那我就获取用户信息并保存在vuex中,这里遇到一个问题就是token会出现过期的情况,那我就删除了本地的user_token,window.localStorage.removeItem("user_token");刷新页面 router.go(0);这个时候就重新走了一遍如果没有token的情况。
    第一版方法

    
     router.beforeEach((to, from, next) => {
          //   第一次进入项目
          let token = window.localStorage.getItem("user_token");
          
          if (!token && to.path != "/author") {
            window.localStorage.setItem("beforeLoginUrl", to.fullPath); // 保存用户进入的url
            next("/author");
            return false;
          } else if (token && !store.getters.userInfo) {
          //获取用户信息接口
            store
              .dispatch("GetUserInfo", {
                user_token: token
              })
              .catch(err => {
                window.localStorage.removeItem("user_token");
                router.go(0);
                return false;
              });
          }
          next();
        });
    

    2018-08-14第二版方法
    不同的地方是将跳转判断从author.vue里拿出来放这里了逻辑其实很简单,有token获取信息,没token跳转授权

    
    router.beforeEach((to, from, next) => {
      
      const token = window.localStorage.getItem('user_token')
      if (token) {
        if (to.path === '/author') {
          next({
            path: '/'
          })
        } else {
          store
            .dispatch('GetUserInfo', {
              user_token: token
            })
            .then(res => {
              // 拉取用户信息
              next()
            })
        }
      } else {
        if (to.path !== '/author') {
          // 保存用户进入的url
          if (to.path === '/shop' || to.path === '/product') {
            window.localStorage.setItem('authUrl', to.fullPath) // 保存用户进入的url
          }
          store.dispatch('GetAuthUrl').then(res => {
            // 此处返回的是后台拼接的微信授权地址,前台也是可以拼接的,跳转到微信授权
            window.location.href = res.data.url //https://open.weixin.qq.com/connect/oauth2/authorize?appid=aaaaa&redirect_uri=后端java或php地址&response_type=code&scope=snsapi_userinfo&state=STATE&connect_redirect=1#wechat_redirect
          })
        } else {
          next()
        }
      }
    })
    

    下面就是进入author.vue的逻辑,第一次进入author, www.xxxx.com/h5/author,判断链接有没有token参数,如果没有就跳微信授权,然后后台会重定向回来并携带token,如: www.xxxx.com/h5/author?token=xxxxxxxxx&msg=200

    第一版

    
     
    <template>
       <div>
    授权中。。。
       </div>
    </template>
    
    <script>
      
       import {
          getWxAuth
       } from '@/service/getData'
       import {
          GetQueryString 
       } from '@/utils/mixin';
       export default {
          data() {
             return {
                token: '',
             };
          },
          computed: {
           
          },
          created() {
             this.token =  window.localStorage.getItem("user_token");
             //判断当前的url有没有token参数,如果不存在那就跳转到微信授权的url
             //就是前面说的ReturnGetCodeUrl方法
      
             if (!GetQueryString("token")) {
                this.ReturnGetCodeUrl();
             } else {
               //如果有token,如http://www.xxxx.com/h5/author?token=xxxxxxxxx&msg=200,这里的参数就是后台重定向到前台http://www.xxxx.com/h5/author,并携带的参数。这样就可以拿到我们想要的token了
               //判断一下后台返回的状态码msg,因为可能出现微信拿不到token的情况
                let msg = GetQueryString("msg")
                if (msg = 200) {
                   this.token = GetQueryString("token");
                   //存储token到本地
                    window.localStorage.setItem("user_token", this.token);
                    //获取beforeLoginUrl,我们的前端页面
                   let url =  window.localStorage.getItem("beforeLoginUrl");
                   //跳转
                   this.$router.push(url);
                   //删除本地beforeLoginUrl
                   removeLocalStorage("beforeLoginUrl");
                }else{
                //msg不是200的情况,可能跳到404的错误页面
                }
             }
          },
          methods: {
           
             async ReturnGetCodeUrl() {
                let {
                   data
                } = await getWxAuth({});
                if (data.status == 200) {
                  
                   window.location.href = data.url;
                }
             },
    
             
          },
          watch: {},
    
          components: {},
    
    
          mounted: function () {}
       }
    </script>
    <style lang='scss' scoped>
    
    </style>
    

    GetQueryString方法

    mixin.js

    
    export const GetQueryString = name => {
      var url = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
      var newUrl = window.location.search.substr(1).match(url);
      if (newUrl != null) {
        return unescape(newUrl[2]);
      } else {
        return false;
      }
    };
    
    

    第二版
    只用来后台拿到参数返回到author页面后的携带的参数如果获取成功则跳转到授权之前保存的url如果失败提示用户关闭网页重新授权,另外有一点值得注意,微信名里有特殊字符的需要转码要不授权会失败

    
    <!-- author -->
    <template>
      <div>
        授权中。。。
      </div>
    </template>
    
    <script>
      import {
        mapGetters
      } from 'vuex'
      import {
        Toast
      } from 'mint-ui'
      import {
        GetQueryString,
        setLocalStorage,
        getLocalStorage,
        removeLocalStorage
      } from '@/utils'
      export default {
        data() {
          return {
            token: ''
          }
        },
        computed: {
          ...mapGetters([
            'userInfo'
          ])
        },
        created() {
          const wxtoken = GetQueryString('token')
          const code = GetQueryString('msg')
          if (wxtoken && Number(code) === 200) {
            setLocalStorage('user_token', wxtoken)
            const historyUrl = getLocalStorage('authUrl')
            this.$router.replace(historyUrl)
            //  removeLocalStorage('authUrl')
          } else {
            // 没有拿到后台访问微信返回的token
            Toast('授权失败请关闭网页重新进入')
            removeLocalStorage('share_token')
            removeLocalStorage('authUrl')
          }
        }
      }
    
    </script>
    <style lang='scss' scoped>
    
    
    </style>
    
    

    整个过程是可以实现授权,但是觉得代码写得不好,以后的开发中希望能够有更优的方法。希望能和大家交流学习。
    2018-08-14更新,总结一下,第二次开发流程做了简化,但是整个思路还是一样,我之前想到过另外一种方法,是将我的那串长参数先保存在本地,然后去授权的时候就可以让后台帮我跳转到固定页面如/product我在从本地拿参数解析,这个方法应该也是可行的,下次尝试后更新

    原文地址:https://segmentfault.com/a/1190000014255151

  • 相关阅读:
    Git总结
    MongoDB基础总结
    Docker总结
    Java总结
    jQuery总结
    Bootstrap4总结
    QQ企业通--客户端登陆模块设计---知识点
    INI文件,WritePrivateProfileString()和GetPrivateProfileString()函数----转载
    C#调用Win32 的API函数--User32.dll ----转载
    C# 中[DllImport("user32.dll")]和extern用法和示例----转载
  • 原文地址:https://www.cnblogs.com/lalalagq/p/9917101.html
Copyright © 2011-2022 走看看