小程序开发-梳理登陆流程-v1.0

最近发现小程序的登陆逻辑还有一些新的心得,因此记录一下。html

1、官方微信小程序登陆流程我的理解

在小程序官网里面会提到一个小程序的登陆逻辑,这是官方推荐的登陆逻辑,也就是所谓的小程序登陆态维护逻辑,这里是官方的图:redis

官方逻辑的我的理解:数据库

  1. 用户打开微信小程序。
    • 也能够是在须要的时候处理这个逻辑,不必定是打开小程序的时候执行这个逻辑。
    • 具体看业务须要,可是每每不少业务设计都是要用户打开小程序的时候,来运行这个逻辑的。
  2. 小程序经过wx.login获取微信的 code,而后将这个 code 发送给开发者服务器(咱们本身的开发服务器)。
  3. 开发者服务器接收到code 以后,会进行封装处理,经过code2Session这个api 接口来获取真正须要的微信用户的登陆态session_keyopenidunionid
    • 准确来讲session_key才是真正的微信登陆态信息,可是把 openidunionid加起来一块儿理解,也能够笼统地理解为这些都是微信的登陆态信息。
  4. 而后须要开发者服务器本身生成一个自定义的登陆态(例如业务 token或者 session)来保存这些微信服务器返回来的微信登陆态相关信息(session_keyopenidunionid),而且作关联处理,而后返回给小程序客户端。
    • 关联处理就是你的自定义登陆态和微信的登陆态相关联,这样的话就不须要维护多个登陆态,只须要维护一个就能够了。
    • 关联处理以后须要将这个自定义登陆态信息保存起来,能够放到数据库或者本地文件或者 例如 redis 之类的缓存服务里面,以便方便后续使用,而不须要每次都请求微信服务器(微信服务器对这个请求的频率是有限制的)
    • 注意这里不返回微信登陆态相关信息,只返回自定义的登陆态信息。
    • 自定义登陆态的信息不只能够包含 token,也能够包含一些用户权限信息,或者其余信息,由于是自定义的登陆态,维护也是很自定义的。
    • 通常自定义的登陆态的超时时长须要比微信的登陆态要长。
  5. 小程序客户端接收到返回的自定义登陆态信息,从而判断用户是否登陆成功,登陆成功的话,就将自定义登陆态信息保存到本地的存储。
    • 本地的存储能够是微信小程序提供的 app.globaldata,也能够是 localstoage,注意,小程序不支持 cookie
    • 保存到本地存储的好处就是,后续使用的这个自定义登陆态就不须要再次跟服务器进行交互来获取了,只须要调用本地存储就好了,这里是为了优化性能和避免浪费资源。
  6. 小程序客户端访问业务接口的时候,携带以前保存到本地存储的自定义登陆态信息进行对开发者服务器(业务接口服务器)访问。
  7. 开发者服务器的业务接口接收到请求,而且请求里面携带了自定义的登陆态,经过校验以后,会返回相关信息。
    • 校验是将小程序客户端携带过来的自定义登陆态和开发者服务器缓存起来的自定义登陆态进行对比,会去确认是否和用户的 openid或者 unionidsession_key 相匹配。
    • 若是匹配,就能够立刻返回相关信息。
    • 若是不匹配,就能够立刻返回相关信息,告知小程序客户端没法访问业务接口。
    • 若是匹配结果是自定义登陆态超时了,就能够立刻返回相关信息,告知小程序客户端须要从新运行登陆逻辑
    • 若是是匹配结果是自定义登陆态没有超时,可是微信登陆态超时了,那么就会开发者服务器就会再次发起code2Session进行微信登陆态更新。

整个微信小程序官方推荐的登陆态维护流程就是这样了,官方推荐使用自定义登陆态来进行整个微信小程序的登陆维护,既然寄人篱下,那么就要循序渐进,跟着政策走,这是最好的应对。小程序

上面的图里面的一些术语解释:微信小程序

  • code 是微信用户的登陆凭证,打开小程序登陆的时候获取的只属于微信这个用户的登陆凭证,须要注意的是,这个登陆凭证只供微信小程序使用的。api

  • 这个 code 的存活时间通常是5分钟左右,这是一个临时的登陆凭证,他的最大做用就是肯定是来源自哪个微信用户来打开,是为了后续生成一个微信登陆态 session_key而使用的。promise

  • session_key 是微信用户在小程序里面的登陆态信息,这是微信给这个用户颁发的一个登陆 session缓存

    • 他的返回格式{"session_key",openid":"..."},官方说须要按期使用wx.checkSession检测,可是在实际的场景里面其实也能够不用,用和不用主要看你怎么设计你的微信小程序,这个后续会说。
    • 早起官方是返回 expire_time 过时时间的,可是后面取消了,这里有一个比较新的官方回复:用户越频繁使用小程序,session_key有效期越长,…… | 微信开放社区,有效期是3天,可是这个不必定是固定的,具体看业务需求,总的原则就是维护一个自定义登陆态,自定义登陆须要和微信登陆态关联。
  • openId ,用户在微信里面的惟一标识,可是须要跟 unionid 进行一块儿理解。
  • unioinId,若是开发者拥有多个移动应用、网站应用、和公众账号(包括小程序),可经过unionid来区分用户的惟一性,由于只要是同一个微信开放平台账号下的移动应用、网站应用和公众账号(包括小程序),用户的unionid是惟一的。换句话说,同一用户,对同一个微信开放平台下的不一样应用,unionid是相同的。
    • 通常来讲,openId 就是微信用户的惟一标识,可是由于微信产品不少,因此会出现多个微信产品使用不一样的 openId 来标识用户,可是对于咱们作业务接入的话,就买办法使用了,因此建议是统一使用 unioinid,由于通常来讲,通常的业务都会有公众号,小程序联合使用的,因此 unionid 使用频率较高。
  • 3rd_session 是通常是指开发者服务器的登陆态,也就是自定义登陆态,也就是咱们本身公司的业务服务器的登陆态(微信官方推荐使用自定义登陆态来管理整个微信小程序登陆)。
    • 当小程序登陆态过时了,自定义登陆态没过时的时候,那么就须要在小程序打开的时候先执行一次wx.checkSession来检查,若是过时了,就本地执行登陆操做,再让开发者服务器跟微信服务器交互,获取新的小程序登陆态,而后关联到自定义登陆态。
    • 当小程序登陆态没过时,自定义登陆态过时了的时候,那么小程序客户端访问业务接口的时候,业务接口会告诉小程序客户端,你的自定义登陆态超时了,而后小程序客户端会从新执行登陆逻辑,而后通知开发者服务从新生成新的自定义登陆态,而后关联以前还在使用的小程序登陆态。
    • 当两者都同时过时的时候,那就确定要发起完整的从新登陆了。
    • 这样的好处是自定义登陆态不须要重复建立,也能跟小程序登陆态一块儿维护管理,达到资源合理利用的效果。
  • 小程序的登陆态可使用微信返回的 session_key 做为表明理解。
  • 自定义登陆态是开发者服务器建立的,也是业务的登陆态,通常是指咱们业务本身的 session会话,官方说的3rd_session就是这个。
  • 通常自定义登陆态的管理都会使用相似 redis 之类的东西来进行管理的,这里也涉及到一个自定义登陆态的缓存策略,缓存起来,在必定时间内不须要从新建立自定义登陆态,达到优化性能的效果。

只有理解好官方的标准流程,才能更好地理解其余流程,或者其余人对官方流程的封装和注解!服务器

2、扩展微信小程序登陆流程

上面是基本的登陆流程理解,可是实际业务中仍是会有一些地方须要补充的,可是咱们理解的时候最好把他们分开,这样会更清晰和简单。微信

按照官方推荐的方式是使用自定义登陆态来管理整个微信小程序登陆流程的,虽说是经过一个自定义登陆态来管理,可是其实里面是有变通的。

这里有2种方式来作:

  1. 方式一:小程序打开的时候先检查小程序本地是否有存储的自定义登陆态,

    • 若是没有,则表明是首次登陆,要自动执行完整的登陆流程,

    • 若是有,则须要判断这个自定义登陆态是否过时,这里判断的方式有2种,一种是开发者服务器提供一个接口来检查,一种是在这个自定义登陆态数据里面加上过时时间,判断是否过时。

      • 过时,则自动发起完整的登陆流程。
      • 不过时,就继续使用本地保存的自定义登陆态。
  2. 方式二:小程序打开的时候先发起wx.checkSession检查微信登陆态是否过时:

    1. 若是过时,则发起完整的登陆流程。
    2. 若是不过时,则继续使用本地保存的自定义登陆态。(若是本地的自定义登陆态没有的话,那么也是要强制发起完整的登陆流程的)

上面说的方式都是打开小程序的时候作的,可是也要考虑到一种状况,就是自定义登陆态在用户使用小程序的过程当中过时了,那么这时候也是须要强制执行完整的登陆流程的。

相对来讲方式二比较好,方式二的好处是不须要小程序服务端来参与校验,而是在小程序端调用API。这种方式其实是将维护登陆态的机制委托给了微信维护的session_key,开发者不须要在自定义的登陆态中保存有效期信息。腾讯云开发的wafer项目便采起了这种方法。

3、继续扩展微信小程序登陆流程

上面提到的方式二是在打开小程序的时候作的,这里是在每次发起 HTTP 请求的时候作的,这个是不同的逻辑。

当小程序客户端访问接口的时候,开发者服务器返回说你的自定义登陆态过时了,你就须要从新发起完整的登陆,但这里有2个点是须要注意的:

  1. 因为 HTTP 是无状态的,因此不能跟踪状态,发起 HTTP 请求而后服务器返回自定义登陆态过时的结果,而后就完结了,没办法暂存起原来的 HTTP 请求,以便当咱们有可用的自定义登陆态的时候,继续使用。因此咱们须要在发起 HTTP 请求的时候作判断,看是否须要发起完整的登陆流程。
  2. 在小程序里面,常常会有访问开发者服务器的状况,可是若是每一个接口都须要这样直接判断的话,就会产生不少冗余代码,并且没办法维护,万一登陆流程改变了,就要所有代码改一遍了。

因此这里就须要进行封装一下,Random Notes这里就提到了,思路是正确的,不过实现的话能够按本身须要实现,他这里有2个地方描述得很好,因此我搬过来借鉴了。

这是一个宏观的,每一个请求都要检查一下登陆态的逻辑图:

图片引用自: blog.imtouch.info

每一个请求都会检查一次登陆态,不论是自定义登陆态仍是微信登陆态,反正只要发起跟开发者服务器交互的 HTTP 请求的以前都会检查。

细分逻辑的话就会变成这样:

图片引用自: blog.imtouch.info

细分逻辑以后看起来会更加清晰,而且这里的逻辑是微信登陆态和自定义登陆态都会检查一遍,任何一个登陆态过时都会发起完整的登陆逻辑,其实我以为这里也能够只判断自定义登陆态的状态也能够的。

不过由此也带来一个问题,就是若是一个页面里面有多个请求同时发起的话,那么就会出现同时检查到登陆态过时,而后同时发起登陆的状况,这个问题可能会致使开发者服务器的校验登陆数据出现问题,他这里用到 promise.race 来解决,具体能够看他的文章里面介绍,我后面也会继续写一下这个处理的介绍。

参考文档:

相关文章
相关标签/搜索