微信小程序自动登录逻辑分析与实现,页面黑白名单管理(上)

一、 需求与逻辑分析

产品需求为进入小程序,实现用户的自动登录。由于已经完成了app端和h5端的产品,用户登录也加入了第三方登录,在后台区分用户是根据手机号,因此各个平台的登录最主要的是与手机号绑定。而qq,微信公众号和小程序平台决定用互通的unionId,不使用OpenId登录,最终将uniodId与对应的手机号关联。
小程序平台有两种登录方式,一种是账户密码登录,另一种是微信自动登录。


登录页面

登录页面逻辑展现

二、自动登录的切入点和冲突

将登录页作为初始页,在进入登录页时先执行自动登录,如果通过wx.login可以获取uniodId,用户也绑定了手机号,就可以成功登录,否则跳转相应的页面。
起初是决定将自动登录放进app.js的生命周期onShow里执行,保证每次进入小程序都可以执行自动登录,但是这里就有了冲突。
如果是进入了其他页面,例如登录页->a->b->c,这时候突然退出刷了下微博,小程序进入了后台状态,再进入小程序,还是c页面,但这时候app.js也会重新执行。
假定c页面是我的资料页面,接口也会审查用户登录状态,如果登录状态掉线,未登录c.js的处理逻辑是跳转登录页。app.js和c.js是异步的,这俩js都检查到了用户未登录状态,这时候就会导致跳转两次登录页。
删除掉c.js接口相关的判断显然是不合理的。那么该如何处理这种app.js和进入的页面.js的冲突呢?
两种方案:
1.app.js的onShow周期下确保初始页为登录页时,执行自动登录。其他的等待页面接口判断用户是否登录,再跳转用户登录。这种的坏处是其他页面需要增加的逻辑比较多,稍微复杂。
2.进入小程序onLaunch执行登录,其他情况自动登录根据页面黑白名单验证的判断,在需要判断登录的页面加上登录状态过滤,进入页面需要登录的就用loginCheck,点击页面某个方法判断未登录状态跳转登录的调goLogin。大型项目提前做好构建后续会省事很多(由于篇幅原因,第二种方案我会另写一篇文章:微信小程序自动登录逻辑分析与实现,页面黑白名单管理(下))。
3.将app.js和需要判断用户登录状态页面.js的异步操作改成同步,这样确保app.js执行完登陆后再处理其他页面逻辑,就不会造成重复登录的状态。

三、使用
1.如果小程序页面较少,单个页面处理逻辑也很方便,采用第一种方案:

//app.js
App({
  onLaunch: function () {
    this.firstLogin();
  },
  firstLogin: function () {
    let that = this;
    wx.login({
      success: res => {
        if (res.code) {
          ajax.request({
            url: '/api/system/wx?code=' + res.code,
            method: 'get',
            success: res => {
              if (res.statusCode == 200 && res.data.openid) {
                that.globalData.openId = res.data.openid;
                let nowRoute = ajax.getCurrentPageUrlWithArgs();
                // 判断当前页是否为入口登录页,如果是,自动登录;如果不是,等待用户在页面的操作判断接口是否需要登录
                if (nowRoute == '/pages/login/index') {
                  // 如果有unionid就自动登录
                  if (res.data.unionid) {
                    that.goLogin(res.data.unionid);
                  } else {
                    // F-1-2-3:判断当前是否是登录页,不是跳转登录页
                    // 当前页保存在缓存
                    let nowRoute = ajax.getCurrentPageUrlWithArgs();
                    wx.redirectTo({
                      url: '/pages/login/index'
                    })
                  }
                }
              }
            },
            fail: function (error) {
              console.log(error)
            }
          });
        } else {
          // 微信登录失败
          wx.showToast({
            title: '网络异常,请稍后重试',
            duration: 2000,
            icon: 'none'
          })
        }
      },
      fail: res => { },
      complete: res => { },
    })
  },
// 微信登录
  goLogin: function (unionid) {
    let that = this;
    ajax.request({
      url: '/api/user/第三方登录',
      data: {
        LoginType: 'weixin',
        unionid: unionid
      },
      method: 'post',
      success: res => {
        // unionid保存在全局,保存手机号
        that.globalData.unionid = unionid;
        if (that.unionidCallback) {
          that.unionidCallback(unionid);
        }
        if (res.statusCode == 200) {
          if (res.data.code == 0 && res.data.data.usertoken) {
            //  登录成功,保存相关信息,跳转首页
            wx.redirectTo({
              url: "/pages/index"
            })
          } else if (res.data.code == -1){
            //用户未绑定手机号,选择绑定手机或者使用账户密码登录
            wx.showModal({
              title: '提示',
              content: '该微信账户未绑定手机号,是否使用账户密码登录?',
              cancelText: '密码登录',
              confirmText:'绑定手机',
              success(res) {
                if (res.confirm) {
                  // 绑定手机号
                  wx.redirectTo({
                    url: '/pages/login/phone/index'
                  })
                } else if (res.cancel) {
                  // 使用账户密码登录
                  wx.redirectTo({
                    url: '/pages/login/index'
                  })
                }
              }
            })
          } else{
            wx.showToast({
              title: '网络异常,请稍后重试',
              duration: 10000,
              icon: 'none'
            })
          }
        }
      },
      fail: function (error) {
        console.log(error)
        wx.showToast({
          title: '登录失败,请检查网络稍后重试',
          duration: 2000,
          icon: 'none'
        })
      }
    });
  },
  globalData: {
    openId: '',
    unionid: '',
  }
})

重点贴一下无unionid跳转的中间授权页的代码,解密encryptedData用了decryption.js+crypto.js


中间页授权获取unionid
// decryption.js
const CryptoJS = require('./crypto-js/crypto-js.js');
// 获取用户信息解密
function decryptUserInfo(session_key, encryptedData, iv) {
  // var encryptedData = CryptoJS.enc.Base64.parse(encryptedData);
  var key = CryptoJS.enc.Base64.parse(session_key);
  var iv = CryptoJS.enc.Base64.parse(iv);
  try {
    // 解密    
    var decrypted = CryptoJS.AES.decrypt(encryptedData, key, {
      asBpytes: true,
      iv: iv,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
    });
    var decryptResult = CryptoJS.enc.Utf8.stringify(decrypted).toString();
    var value = JSON.parse(decryptResult);
  } catch (err) {
    console.log(err);
  }
  return value;
}

module.exports = {
  decryptUserInfo: decryptUserInfo
}

// pages/fastlogin/fastlogin.js 
const app = getApp();
const jiemi = require('../../../utils/decryption.js');
Component({
  /**
   * 组件的初始数据
   */
  data: {
    nickname: '',
    photopath: '',
    gender: ''
  },

  /**
   * 组件的方法列表
   */
  methods: {
    // 1.关注用户是否授权,未授权页面停留,授权后获取加密信息
    onGotUserInfo(e) {
      let that = this;
      if (e.detail.errMsg == "getUserInfo:ok") {
        console.log(e, '已经授权用户信息');
        this.getLcode(e.detail.encryptedData, e.detail.iv);
      } else {
        console.log("用户未同意授权")
      }
    },
    // 2.解密unionId
    getLcode(encryptedData, iv) {
      let that = this;
      wx.login({
        success: res => {
          if (res.code) {
            ajax.dotnetRequest({
              url: '/api/system/WX?type=2&code=' + res.code,
              method: 'get',
              success: sessionRes => {
                if (sessionRes.statusCode == 200 && sessionRes.data.session_key) {
                  //  2-1:解密unionid
                  let jiemiRes = jiemi.decryptUserInfo(sessionRes.data.session_key, encryptedData, iv);
                  let unionId = jiemiRes.unionId;
                  // 2-2:获取成功,执行登录
                  if (unionId) {
                    app.goLogin(unionId)
                  }                
                }
              },
              fail: function (error) {
                console.log(error)
              }
            });
          } else {
            console.log(res, 'code获取失败');
          }
        },
        fail: res => {
          console.log(res, 'code获取失败');
        },
        complete: res => { },
      })
    },
  }
})
···



最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,743评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,296评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,285评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,485评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,581评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,821评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,960评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,719评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,186评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,516评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,650评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,936评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,757评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,991评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,370评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,527评论 2 349