vue hash模式下微信授权登录

背景

vue-cli项目。路由是hash模式。需要授权的场景有:项目入口处(App.vue),指定页面(创建时、methods 方法内);可以携带参数

思路

由于hash模式# 号的存在,授权后链接会被扰乱。所以 我希望在 授权前 将重定向的链接 即 redirect_uri 改为没有# 的url。然后在 项目入口处 进行 url 重置,将其改回到 丑陋的 带#链接。

即:两步操作

1、授权前 将redirect_uri 改为没有# 的url

2、项目入口处,将没有#的url改回到 带#的url,跳到指定页面。

主要代码

1、授权前,redirect_uri 重置

这里会将当前页面的原有参数信息、额外参数、codepath参数 作为 redirect_uri 的新参数。其中codepath是 用来指定 跳转页面的,通常为 授权发起页。

/**
   * 开始设置页面链接,进行code 授权重定向
   *
   * @param scope 授权作用域
   * @param path  授权所在页面 path
   * @param extraPm 额外参数,需要在 配置中 进行参数配置
   * @returns {string}
   */
  get_codeV3(scope, path, extraPm={}) {
        if (process.env.NODE_ENV === 'development' && config.isMockWeChat)
          return '0713eFVW0AmFP12kGVTW0oGDVW03eFV2'

      let homeUrl = '', searchOb = {}, searchstr = ''
      let oriUrls = window.location.href.split('?')
      let baseShareURl = window.location.origin + window.location.pathname
      homeUrl = baseShareURl
      if (oriUrls.length > 1) {
        let searchUrls = oriUrls[1].split('#')
        let searchUrlReal = searchUrls[0]
        searchOb = qs.parse(searchUrlReal)
        let {code} = searchOb
        if (code)
          delete searchOb.code
      }
      searchOb.codepath = path
      Object.assign(searchOb, extraPm)
      searchstr = `?${qs.stringify(searchOb)}`
      homeUrl += searchstr

      let redirect_uri = encodeURIComponent(homeUrl);

      let response_type = 'code';
      // 应用授权作用域,
      // snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),
      // snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )

      // 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
      let state = '';
      let url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirect_uri}&response_type=${response_type}&scope=${scope}&state=${state}#wechat_redirect`;
      window.location.href = url;
    }

2、链接前置判断

在项目入口处,发现有 codepath 参数,即 将该链接视为 授权后的redirect_uri 链接。进行页面重定向,跳转到 codepath 指定页面

/**
   * 页面重定向(授权)-确保页面链接正常
   * 支持多参、无参、指定页面
  * code 在 返回的search 里 * @returns {{needRedirect: boolean, homeUrl: string, search: {}}}
*/ urlResetForWxCode: function () { //需要重定向时:codepath 参数 与 code 参数同在。 let needRedirect = false, homeUrl = '', searchOb = {}, searchstr = '' let oriUrls = window.location.href.split('?') let baseShareURl = window.location.origin + window.location.pathname homeUrl = baseShareURl if (oriUrls.length > 1) { let searchUrls = oriUrls[1].split('#') let searchUrlReal = searchUrls[0] let searchObReal = {} searchOb = qs.parse(searchUrlReal) let { codepath } = searchOb needRedirect = codepath if (codepath) { config.platform.wxCode[codepath].forEach(item => searchObReal[item] = searchOb[item]) if (config.platform.wxCode[codepath].length) searchstr = `?${qs.stringify(searchObReal)}` homeUrl += `#${codepath}` + (searchstr.length > 1 ? searchstr : '') } } return { needRedirect, homeUrl, search: searchOb } }

// 配置信息

config = {
  platform: {
    wxCode: {'/': ['hello', 'yiha'], '/spe': ['spp']}, // 微信授权-需要授权的页面: [页面用到的参数]
  }

 

使用

1、授权发起位置通常有 项目入口处、页面create 时,页面 指定方法内。

if (!storage.getToken()) {// code 授权标志 保存在localstorage。
        wx_jssdk.get_codeV3('snsapi_userinfo', '/')
        return
      }

2、项目入口处进行前置判断

// App.vue

created(){

      // 可以在项目入口处 进行code授权
      if (!storage.getToken()) {// code 授权标志 保存在localstorage。
        wx_jssdk.get_codeV3('snsapi_userinfo', '/')
        return
      }
      // 项目只要用到授权,则需要进行重定向判断。
      let {needRedirect, homeUrl, search} = browserUtil.urlResetForWxCode()
      if (needRedirect) {
        storage.setToken({code: search.code}) // 保存code
        window.location.href = homeUrl
      }

    }

 

 写在最后

想着尽量能够做到配置化、可扩展,目前很low。凑合用吧😄

配置化的体现:

链接前置判断方法内,组装链接参数时,我是只拿配置信息里的存在的参数。(方法里飘红的代码)。这是为了参数可控,避免不必要的bug。

可扩展的体现:

在redirect_uri 重置方法 参数里,有一个额外参数,原本 想着只截取授权发起页的原始search参数就好了。但一想 会不会有这样的使用场景:

表单提交页,在提交时 才去发起授权。这样的话 可能授权后 原表单信息已丢失,即需要重新再来;体验并不好。那么可不可以 将表单数据作为 授权时的一部分参数,然后在授权成功后,页面重新create时 检测到有表单数据时 直接提交。(当然,你也可以通过local保存数据来实现这个功能,或者其他)

注:该额外参数 也需要在配置里注明,不然 前置判断里 会不予理会。

posted @ 2019-07-26 15:18  点几  阅读(7432)  评论(0编辑  收藏  举报