小程序|大龄业余程序员要搞个django小程序--08--深入理解小程序登陆状态的维护

业余水平第一次做小程序,进度非常慢,每天下班后也只有零碎的1到2小时,一个小问题可以难倒我几个晚上的时间。
由于微信小程序没有一套身份验证管理的框架,只提供wx.loginwx.getUserProfile等几个api,所以对于我这种初学者来说,小程序登陆状态管理就显得很麻烦。经过这段时间的实践,终于摸到了点门槛。先梳理几个重要的信息。
小程序|大龄业余程序员要搞个django小程序--08--深入理解小程序登陆状态的维护
文章图片

从用户使用的层面理解小程序的登陆逻辑 小程序打开时,只会有两种状态

  • 未登陆状态,查看不到个人信息
  • 登陆状态
那,当小程序载入时,依靠什么来判断状态呢?结合官方的文档和实践,我采用以下的逻辑判断登陆状态的设定:
1、sessionKey 是否过期,
2、本地是否有userInfo
经过实践,以上两项,只要有一项不满足,都必须显性地标识为未登陆sessionKey都过期了,说明这个用户很久没登陆小程序了,有必要走一套登陆的流程,或者,本地连userInfo都没来,即便标识为登陆,也没用,没有基础的用户数据的话,你显示个毛线。
从开发的层面理解小程序的登陆逻辑 用户为两种状态
  • 已注册
  • 未注册
需要考虑以下情况
  • 请求中是否需要携带token,无token则需要验openid,然后签发token;token过期时通知小程序客户端重新执行登陆操作
  • 请求中是否需要携带code iv encryptedData 。按照个人的理解,需要携带。即wx.login(提供code)getUserInfo(提供iv和encryptedData)配合使用,可以随时做openid校验和解密encryptedData信息。
总结 1、小程序客户端使用sessionKeyuserInfo缓存来决定用户在小程序的登陆状态;
而且,都可以在全局进行判断,即项目根目录的app.js
App({ wx.checkSession({success: (res) => { //返回:有效期内的提示}, fail: (res) => { //返回:过期的提示}, complete: (res) => { }, }); let u = wx.getStorageSync('userInfo') console.log(u) //如果不存在,返回的是空字符})

上面并非业务代码,只是做简单的展示,实践中可以考虑使用promise封装起来。
总之,sessionKeyuserInfo只要其中之一不存在,都要把登陆状态标记为未登陆
2、需要把登陆逻辑单独封装,方便在需要的时候使用。
export const wxGetUserProfile = () => {return new Promise((resolve, reject) => {// 登陆中提示 wx.showLoading({title: '登陆中...', mask: true, }) wx.getUserProfile({desc: '授权以提供进一步服务', lang: 'zh_CN', success: (result) => {resolve(result) }, fail: (err) => {reject(err) }, complete: (res) => {wx.hideLoading({ }) }, }) }) }export const wxLogin = () => {return new Promise((resolve, reject) => {wx.login({success: (result) => {resolve(result) }, fail: (err) => {reject(err) }, complete: (res) => {}, }) }) }

使用Promise分别封装wx.loginwx.getUserProfile,使用时要在使用的js中引入封装的方法)
tapToLogin(e) {let p1 = wxLogin() let p2 = wxGetUserProfile() p1.then(code => {return code }).then(code => {return new Promise((resolve, reject) => {p2.then(res => {console.log('profile', res.userInfo); this.setData({userInfo: res.userInfo }) wx.setStorageSync('userInfo', res.userInfo) resolve({code: code.code, iv: res.iv, encryptedData: res.encryptedData, userInfo: res.userInfo }) }).catch(err => {reject(err) }) }) }).then(res => {// 使用封装的request if (!wx.getStorageSync('token')) {request({url: HOST_API.menberLogin, method: "POST", data: {code: res.code, iv: res.iv, encryptedData: res.encryptedData } }) .then(result => {wx.setStorageSync('token', result.data.context.token); this.setData({hasUserInfo: true, isLogin: result.data.context.is_login, isVip: result.data.context.is_vip, collection: result.data.context.collection, integration: result.data.context.integration, views: result.data.context.views }) console.log('无头的返回:', result); }) } else {request({url: HOST_API.menberLogin, method: "POST" }) .then((result) => {console.log('有token的返回:', result); this.setData({hasUserInfo: true, isLogin: result.data.context.is_login, isVip: result.data.context.is_vip, collection: result.data.context.collection, integration: result.data.context.integration, views: result.data.context.views }) }) } }) },

未登陆状态
小程序|大龄业余程序员要搞个django小程序--08--深入理解小程序登陆状态的维护
文章图片

登陆状态
小程序|大龄业余程序员要搞个django小程序--08--深入理解小程序登陆状态的维护
文章图片

小程序|大龄业余程序员要搞个django小程序--08--深入理解小程序登陆状态的维护
文章图片

当然,在使用时还是存在逻辑上不清晰的情况。
【小程序|大龄业余程序员要搞个django小程序--08--深入理解小程序登陆状态的维护】3、设置的问题
  • isLogin bool设置为全局变量,注意这个不能设置为缓存。
  • wx.checkSessionwx.getStorageSync('userInfo') 封装好,可以在全局调用,可以在需要的环节进行调用,并且,必须相应地改更全局变量isLogin的值。
  • tokenuserInfo要写到缓存中
  • 可以写一个登陆页面的模板,供各个页面调用。当然,不写模版似乎也没啥问题,但必须,当前的界面在点击授权登陆后,要有显性的提示:登陆完成云云。不然用户不清楚、不确定是否登陆成功。

    推荐阅读