浏览量:589次
对于登录/注册的设计如此精雕细琢的目的,当然是想让这个作为应用的基础能力,有足够的健壮性,避免出现全站性的阻塞。
同时要充分考虑如何解耦和封装,在开展新的小程序的时候,能更快的去复用能力,避免重复采坑。
登录注册这模块,就像个冰山,我们以为它就是「输入账号密码,就完成登录了」,但实际下面还有各种需要考虑的问题。
在此,跟在座的各位分享一下,最近做完一个小程序登录/注册模块之后,沉淀下来的一些设计经验和想法。
在用户浏览小程序的过程中,由业务需要,往往需要获取用户的一些基本信息,常见的有:
而不同的产品,对于用户的信息要求不尽相同,也会有不一样的授权流程。
第一种,常见于电商系统中,用户购买商品的时候,为了识别用户多平台的账号,往往用手机号去做一个联系,这时候需要用户去授权手机号。
第二种,为了让用户信息得到基本的初始化,往往需要更进一步获取用户信息:如微信昵称,unionId 等,就需要询问用户授权。
第三种,囊括第一种,第二种。
秉着沉淀一套通用的小程序登录方案和服务为目标,我们去分析一下业务,得出变量。
在做技术设计之前,讲点必要的废话,对一些概念进行基本调频。
登录在英文中是 「login」,对应的还有 「logout」。而登录之前,你需要拥有一个账号,就要 「register」(or sign up)。
话说一开始的产品是没有登录/注册功能的,用的人多了就慢慢有了。出于产品本身的需求,需要对「用户」进行身份识别。
在现实社会中,我们每个人都有一个身份ID:身份证。当我到了16岁的时候,第一次去公安局领身份证的时候,就完成了一次「注册」行为。然后我去网吧上网,身份证刷一下,完成了一次「登录」行为。
那么对于虚拟世界的互联网来说,这个身份证明就是「账号+密码」。
常见的登录/注册方式有:
账号密码注册
在互联网的早期,个人邮箱和手机覆盖度小。所以,就需要用户自己想一个账号名,我们注册个QQ号,就是这种形式。
邮箱地址注册
千禧年之后,PC互联网时代快速普及,我们都创建了属于自己的个人邮箱。加上QQ也自带邮箱账号。由于邮箱具有个人私密性,且能够进行信息的沟通,因此,大部分网站开始采用邮箱账号作为用户名来进行注册,并且会在注册的过程中要求登录到相应邮箱内查收激活邮件,验证我们对该注册邮箱的所有权。
手机号码注册
在互联网普及之后,智能手机与移动互联网发展迅猛。手机也成为每个人必不可少的移动设备,同时移动互联网也已经深深融入每个人的现代生活当中。所以,相较于邮箱,目前手机号码与个人的联系更加紧密,而且越来越多的移动应用出现,采用手机号码作为用户名的注册方式也得到了广泛的使用。
到了 2020 年,微信用户规模达 12 亿。那么,微信账号,起码在中国,已成为新一代互联网世界的「身份标识」。
而对微信小程序而言,天然就能知道当前用户的微信账号ID。微信允许小程序应用,能在用户无感知的情况下,悄无声息的「登录」到我们的小程序应用中去,这个就是我们经常称之为的「静默登录」。
其实微信小程序的登录,跟传统 Web 应用的「单点登录」本质是一样的概念。
由于 Http 本来是无状态的,业界基本对于登录态的一般做法:
在微信小程序来说,对于「JS逻辑层」并不是一个浏览器环境,自然没有 Cookie,那么通常会使用 access token 的方式。
对于需要更进一步获取用的用户昵称、用户手机号等信息的产品来说。微信出于用户隐私的考虑,需要用户主动同意授权。小程序应用才能获取到这部分信息,这就有了目前流行的小程序「授权用户信息」、「授权手机号」的交互了。
出于不同的用户信息敏感度不同的考虑,微信小程序对于不同的用户信息提供「授权」的方式不尽相同:
梳理清楚了概念之后,我们模块的划分上,可以拆分为两大块:
微信官方提供的登录方案,总结为三步:
如果只是实现这个流程的话,挺简单的。
但要实现一个健壮的登录过程,还需要注意更多的边界情况:
收拢 wx.login() 的调用:
由于 wx.login() 会产生不可预测的副作用,例如会可能导致session_key失效,从而导致后续的授权解密场景中的失败。我们这里可以提供一个像 session.login() 的方法,掌握 wx.login() 控制权,对其做一系列的封装和容错处理。
调用的时机:
通常我们会在应用启动的时候( app.onLaunch() ),去发起静默登录。但这里会由小程序生命周期设计问题而导致的一个异步问题:加载页面的时候,去调用一个需要登录态的后端 API 的时候,前面异步的静态登录过程有可能还没有完成,从而导致请求失败。
当然也可以在第一个需要登录态的接口调用的时候以异步阻塞的方式发起登录调用,这个需要结合良好设计的接口层。
以上讲到的两种场景的详细设计思路下文会讲到。
并发调用的问题:
在业务场景中,难免会出现多处代码需要触发登录,如果遇到极端情况,这多处代码同时间发起调用。那就会造成短时间多次发起登录过程,尽管之前的请求还没有完成。针对这种情况,我们可以以第一个调用为阻塞,后续调用等待结果,就像精子和卵子结合的过程。
未过期调用的问题:
如果我们的登录态未过期,完全可以正常使用的,默认情况就不需再去发起登录过程了。这时候我们可以默认情况下先去检查登录态是否可用,不能用,我们再发起请求。然后还可以提供一个类似 session.login({ force: true })的参数去强行发起登录。
1. 应用启动的时候调用
因为大部分情况都需要依赖登录态,我们会很自然而然的想到把这个调用的时机放到应用启动的时候( app.onLaunch() )来调用。
但是由于原生的小程序启动流程中, App,Page,Component 的生命周期钩子函数,都不支持异步阻塞。
那么我们很容易会遇到 app.onLaunch 发起的「登录过程」在 page.onLoad 的时候还没有完成,我们就无法正确去做一些依赖登录态的操作。
针对这种情况,我们设计了一个状态机的工具:status
基于状态机,我们就可以编写这样的代码:
import { Status } from '@beautywe/plugin-status';// on app.jsApp({ status: { login: new Status('login'); }, onLaunch() { session // 发起静默登录调用 .login() // 把状态机设置为 success .then(() => this.status.login.success()) // 把状态机设置为 fail .catch(() => this.status.login.fail()); }, });// on page.jsPage({ onLoad() { const loginStatus = getApp().status.login; // must 里面会进行状态的判断,例如登录中就等待,登录成功就直接返回,登录失败抛出等。 loginStatus().status.login.must(() => { // 进行一些需要登录态的操作... }); }, });复制代码
[声明]本网转载网络媒体稿件是为了传播更多的信息,此类稿件不代表本网观点,本网不承担此类稿件侵权行为的连带责任。故此,如果您发现本网站的内容侵犯了您的版权,请您的相关内容发至此邮箱【915688610@qq.com】,我们在确认后,会立即删除,保证您的版权。
友情链接加载中...