小程序登录流程全解析

用户登录是一个系统的必备功能。而小程序的登录流程和Web端又有一些不同,主要是要与微信服务器进行通信验证。下面我们就来看下小程序具体的登录流程。

1. 登录流程

小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。

小程序登录时序图

2. 登录逻辑:

  1. 调用 wx.login() 获取 临时登录凭证 code,有效期为 5分钟;(临时登录凭证 code 只能使用一次)

  2. 将临时 code 传到我们的后端,后端调用 auth.code2Session 接口,换取用户唯一标识 OpenID 和 会话密钥 session_key;( openid 是用户唯一标识,session_key 能保证当前用户进行会话操作的有效性)

    注意:获取 session_key 出于安全性的考虑,要在后端调用。如果我们在前端通过 request 调用此接口,就不可避免的需要将我们小程序的appidsecret 和服务端下发的 session_key 暴露在外部,会给我们的业务安全带来极大的风险。 session_key 拥有一定的时效性。用户越久未使用小程序,用户登录态越有可能失效。反之如果用户一直在使用小程序,则用户登录态一直保持有效。具体时效逻辑由微信维护,对开发者透明。开发者需要调用 wx.checkSession 接口检测当前用户登录态是否有效。

  3. 后端自定义新的密钥并关联返回的 session_keyopenid,将新的密钥返给前端,前端将其存储在 storage 中。(会话密钥 session_key 是对用户数据进行 加密签名 的密钥。为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥,所以要定义新的密钥)。 之所以存在storage中,是因为小程序没有 cookie,相应的后端 set-cookie 在小程序中不起作用。

  4. 前端发送请求的时候,带着密钥,后端根据密钥识别用户身份,返回数据。

3. 遇到的问题

在接口报401错误时,对其做登录处理,登录成功后再次调用接口。这种情况下,多接口并行就会出现问题。 因为多接口都会调 wx.login 获取 code 后再调后端的登录接口,而登录凭证 code 只能使用一次,这时候后端对多接口就会接收到不同的 code,返回的自定义密钥就会有多个,不能保持统一。

处理的方案是后端在一定时间内对用户自定义登录态做缓存。接口调 wx.login 获取 code 后再调后端的登录接口时,判断后端缓存中有无此用户,如果没有,返回新的密钥,如果缓存中存在此用户并在缓存有效时间内,就查找并返回之前的密钥。

4. 具体代码

checkSession: 检查登录态是否过期。 通过 wx.login 接口获得的用户登录态拥有一定的时效性。用户越久未使用小程序,用户登录态越有可能失效。反之如果用户一直在使用小程序,则用户登录态一直保持有效。具体时效逻辑由微信维护,对开发者透明。开发者只需要调用 wx.checkSession 接口检测当前用户登录态是否有效。 登录态过期后开发者可以再调用 wx.login 获取新的用户登录态。调用成功说明当前 session_key 未过期,调用失败说明 session_key 已过期。

  checkSession: function () {
    return wx.pro.checkSession().then(res => {
      return Promise.resolve('result1')
    }).catch(err => {
      return this.login()
    })
  },
  
  login: function () {
    return wx.pro.login().then(res => {
      return Promise.resolve(res.code)
    }).then(res => {
      return this.getRequest({
        method: 'POST',
        url: "***/login",
        data: {
          code: res
        }
      })
    }).then(res => {
      let Cookie = res && res.header && res.header['Set-Cookie'] || '';
      Cookie = this.getCookie('cookie-key', Cookie)
      wx.setStorageSync('Cookie', Cookie)
      this.globalData.Cookie = Cookie
      return Promise.resolve('result2')
    }).catch(err => {
      console.log('loginErr', err)
    })
  },
  
  getCookie(name, cookie) {
    let arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
    return (arr = cookie.match(reg)) ? unescape(arr[2]) : null;
  },
  
  getRequest: function (data, tryNum = 1) {
    let header = Object.assign({
      "Content-Type": "application/x-www-form-urlencoded",
    }, data.header)
    if (data.url !== '**/login') {
      header = Object.assign(header, {
        "Cookie": `cookie-key=${this.globalData.Cookie}`
      })
    }
    return new Promise((resolve, reject) => {
      wx.request({
        url: (data.mode !== 'debug' ? Env_config[envObj.env].api : '') + data.url,
        method: data.method || "GET",
        header: header,
        data: data.data,
        success: (res) => {
          if (res && res.statusCode === 200) {
            resolve(res)
          } else if (res.statusCode === 401) {
            wx.showToast({
              title: '登录失效,请重新登录',
              icon: 'none',
            })
            if (tryNum > maxTryNum) return null
            return this.login().then(res => {
              return this.getRequest(data, ++tryNum)
            }).then(res => resolve(res))
                .catch(err => {
                  reject(err)
                })
          } else {
            setTimeout(() => {
              wx.showToast({
                title: res && res.data && res.data.msg || '服务异常,请稍后重试',
                icon: 'none'
              })
            }, 0)
            reject(res)
          }
        },
        fail: (err) => {
          setTimeout(() => {
            wx.showToast({
              title: res && res.data && res.data.msg || '服务异常,请稍后重试',
              icon: 'none'
            })
          }, 0)
          reject(err)
        }
      })
    })
  },
复制代码

在页面中的用法也很简单:

onLoad: function (options) {
  app.checkSession().then(res => {
    this.otherMethods()
  })
}
复制代码

热榜-杂货铺https://www.gzysbb.comicon-default.png?t=LA23https://www.gzysbb.com

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue3+uni-app实现微信小程序登录流程主要分为以下步骤: 1. 在uni-app项目中安装并引入微信小程序登录插件(如wxlogin),在main.js中初始化并配置插件参数。 2. 创建一个登录页面,该页面包含点击按钮触发微信登录的操作,可以通过uni.login()方法调用微信小程序登录接口获取code。 3. 接收到微信小程序登录接口返回的code后,将code发送给后端服务器,后端服务器将code和小程序的App ID以及App Secret发送给微信服务器进行登录凭证校验,获取到session_key和openid。 4. 服务器根据openid和session_key生成一个自定义的token,返回给前端。 5. 前端将token保存在本地,使用uni.setStorage()方法进行存储,以便后续的登录状态维持和接口请求验证。 6. 在需要登录验证的页面或组件中,通过uni.getStorage()方法获取本地存储的token,并将token添加到请求头中,发送给后端服务器进行接口请求。 7. 后端服务器接收到带有token的请求,对token进行校验和解析,验证token是否有效,从而确保用户的登录状态。 总结:通过以上步骤,实现了Vue3+uni-app微信小程序登录流程。用户通过点击按钮触发微信小程序登录接口,后端服务器校验登录凭证,生成token并返回给前端前端保存token并在请求接口时携带token进行验证,保证了用户的登录状态和接口访问权限的安性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值