前端开发踩坑记录

项目

    1. 某电影票务项目(Vue微信公众号项目)

总结:作为离职前的项目整理及今年的立flag产物

电影票务在线售票项目(Vue微信公众号端)

需求:使用Vue重构前端购票页面
技术难点: 1:微信网页登录授权 2:微信JS-SDK ;3:简易版oauth授权认证;

1. 微信网页登录授权

感谢sf社区[Vue微信公众号开发踩坑记录](https://segmentfault.com/a/1190000010753247 的作者提供的在SAP应用上的授权流程思路。
由于项目部署在不同的域上面,架构也不大同意跨域去传输cookie做用户唯一标识,最终采取折中方案为

  • 用户访问网站主域名;
  • vue客户端(domain)接收请求,在路由解析前判断用户是否登录(比如用户信息,uId是否存在);
  • 用户信息不存在,则通过api获取微信授权地址(domain/api/oauthAddress),前端生成一个唯一标识uId并缓存到会话中,同时拼接再跳转到微信服务端授权页面;
  • 用户确认授权,微信服务器发起回调请求,这时需要回调到服务器端(domain/api/xxx);
  • 服务器端获取用户信息同时与uId建立关联并设置时效性,重定向到Vue客户端(domain);
  • 重定向到 Vue客户端,通过uId 去请求(domain/api/getUserInfo)获取用户信息并缓存,进入业务流程

上code

// router.con
import store from '../store/index'
import $http from "../HTTPUtil"
import util from "../util"
router.beforeEach((to, from, next) => {
  // 第一次访问 store uId和 userInfo 并不存在,
  if (!store.state.userInfo && !store.state.uId) {
    // api获取微信授权地址
    $http.post("/oauthAddress")
      .then(res => {
        let data = res.data;
        if (data.code === "0") {
          const uId = util.uId.getUid()
          sotre.commit("setUId", uId) // 生成缓存uId
          let urlArr = data.data.split("#")
          window.location.replace(urlArr[0] + "@" + uId + "#" + urlArr[1]) // 拼接uId,重定向到微信服务端
        }
      })
  } else if (!store.state.userInfo && store.state.uId) {
  // uId存在 ,userInfo不存在
    $http.post("/getUserInfo")
      .then(res => {
        let data = res.data
        if (data.code === "0") {
          sotre.commit("setUId", '') // 清空uId
          sotre.commit("setUserInfo", data.userInfo) // 保存用户信息
          next()
        }
      })
  } else if (store.state.userInfo && !store.state.uId) {
     // 用户信息存在 ,uId不存在
    next()
  }
})

存在弊端

    1. 在一些特殊情况下,前端生成的uId并未能获取到微信用户信息,需要做一定优化处理;
    1. Java后端重定向Vue前端项目,如果是直接重定向到二级路由的页面domian/#/xxxx/yyyy,部分安卓机会直接白屏,后端无法重定向显示白屏。原因未知

2.微信js-sdk及微信支付

  • 由于ios/安卓端存在内核渲染不同,而安卓系统获取的是当前的url地址。ios系统获取签名的url是我们首次进入的地址或者手动刷新的地址(读绿条的时候),在涉及到微信sdk(分享or支付)会无法触发。
    由于是纯前端渲染项目,建议使用hash模式,使用微信提供的JSSDK的时候,不用多次签名当前地址。
  // app.vue
    mouted(){
       $wxConfig._init()
    }

// $wxConfig._init.js
        $http.post('api/wechatSDk', {url:window.location.href.split("#")[0]})
         .then(res=>{
            let data = res.data;
            let config = {
              debug : false
            };
            if(data.code === "0"){
            config = Object.assign(config, data, {
              jsApiList: [ //需要使用的JS接口列表,所有JS接口列表见附录2
                'checkJsApi',
                'onMenuShareAppMessage', // 获取“分享给朋友”按钮点击状态及自定义分享内容接口
                'onMenuShareTimeline', // 获取“分享到朋友圈”按钮点击状态及自定义分享内容接口
                'onMenuShareQQ', // 获取“分享到QQ”按钮点击状态及自定义分享内容接口
                'onMenuShareWeibo', // 获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口
                'getLocation',
                'chooseWXPay',
                'openLocation',
                'scanQRCode',
                ......
              ]
            })
              $wx.config(config)
            }
      })

在用到关于支付功能,跳转到待支付页面在路径上拼接?问号
(window.location.href = window.location.origin + /?#/xxx/yyyy)
完美解决ios端支付无法唤起问题, 同时避开微信公众平台后台授权的url地址只能设置5个的问题;

3. 简易版oauth认证

基于业务安全实现的一套加密oauth, 为前开发人员历时遗留问题,在js的3des加密算法上需要注意一下几点;
//  DESede/ECB/PKCS5Padding
  function des(key, message, encrypt, mode, iv, padding){

  ...

  //pad the message depending on the padding parameter
  if (padding == 2) message += "        "; //pad the message with spaces
  else if (padding == 1) {
    if (encrypt) {// 加密需要计算这一步骤,解密不用
      temp = 8 - (len % 8);
      message += String.fromCharCode(temp, temp, temp, temp, temp, temp, temp, temp);
      if (temp === 8) len += 8;
    }
  } //PKCS7 padding
  else if (!padding) message += "\0\0\0\0\0\0\0\0"; //pad the message out with null bytes

   ....

  // result = result.replace(/\0*$/g, "");// 经验教训 不注释这行代码,会出现最后3des 加密后的hash字符串如果左后几位都是0 会被匹配掉,导致后端无法解析3des加密串;
   ...

  }

你可能感兴趣的:(前端开发踩坑记录)