主机参考:VPS测评参考推荐/专注分享VPS服务器优惠信息!若您是商家可以在本站进行投稿,查看详情!此外我们还提供软文收录、PayPal代付、广告赞助等服务,查看详情! |
我们发布的部分优惠活动文章可能存在时效性,购买时建议在本站搜索商家名称可查看相关文章充分了解该商家!若非中文页面可使用Edge浏览器同步翻译!PayPal代付/收录合作 |
今天微信小程序开发专栏介绍小程序登录的前端设计和实现。1.前言对登录/注册的设计如此阐述,当然是为了把这个作为应用的基础能力,足够健壮,避免全站堵塞。
同时要充分考虑如何解耦打包,这样在开发新的小程序时,可以更快的复用能力,避免重复挖坑。
登录注册的模块就像一座冰山。我们以为是“输入账号密码,登录就完成了”,其实下面还有各种问题要考虑。
在这里,我想和大家分享一下最近做了一个小程序登录/注册模块后沉淀下来的一些设计经验和想法。
2.业务场景用户在浏览小程序的过程中,由于业务需要,往往需要获取用户的一些基本信息。常见的有:
微信昵称微信手机号,不同的产品对用户的信息要求不同,授权流程也不同。
第一种类型常见于电子商务系统。用户在购买商品时,为了识别用户的多平台账号,往往会使用手机号进行联系。这时候用户需要对手机号进行授权。
第二,为了得到用户信息的基本初始化,往往需要进一步获取用户信息,如微信昵称、unionId等。,并且您需要向用户请求授权。
第三类包括第一类和第二类。
3.概念以沉淀一套通用的小程序登录方案和服务为目标,我们来分析一下业务,得出变量。
在做技术设计之前,先说一些必要的废话,对一些概念做基本的调频。
2.1关于英语中的“登录”,login是“登录”,对应的词是“注销”。登录之前需要有账号,所以需要「注册」(或者注册)。
换句话说,该产品一开始并没有登录/注册功能,但随着更多人的使用,它逐渐变得可用。因为产品本身的需求,需要识别“用户”。
在现实世界中,我们每个人都有一个身份ID:身份证。16岁那年,我第一次去公安局拿身份证,就完成了一次“登记”。然后去了网吧,刷了身份证,完成了一个“登录”的行为。
那么对于虚拟世界的互联网来说,这个识别就是“账号+密码”。
常见的登录/注册方法有:
帐户密码注册
互联网早期,个人邮箱和手机的覆盖面很小。所以用户需要自己想一个账号名,我们注册一个QQ号,就是形式。
电子邮件地址注册
千禧年之后,PC互联网时代迅速普及,我们都创建了自己的个人邮箱。此外,QQ还配有自己的电子邮件帐户。因为邮箱是私密的,可以交流信息,所以大部分网站都是以邮箱账号作为用户名开始注册的,并且会在注册过程中要求登录对应邮箱查看激活邮箱,以验证我们对注册邮箱的所有权。
手机号码注册
互联网普及后,智能手机和移动互联网发展迅速。手机也成为了每个人必不可少的移动设备,移动互联网也已经深度融入了每个人的现代生活。因此,与电子邮件相比,目前手机号码与个人的关系更加密切,越来越多的移动应用出现,以手机号码为用户名的注册方式也得到广泛应用。
到2020年,微信用户数量将达到12亿。那么,微信账号,至少在中国,已经成为新一代互联网世界的“身份”。
对于微信小程序来说,自然可以知道当前用户的微信账号ID。微信允许小程序在用户不知情的情况下“登录”我们的小程序。这就是我们常说的“静默登录”。
其实微信小程序的登录和传统Web应用的“单点登录”本质是一个概念。
单点登录:在a站登录后,C站和b站可以实现快速“静默登录”。微信小程序登录:在微信中,只要登录微信账号,就可以在整个小程序生态中实现“静默登录”。因为Http本来就是无状态的,所以业内对于登录状态的通用做法基本如下:
Cookie-session:常用于浏览器应用访问令牌:常用于移动终端等非浏览器应用。对于微信小程序来说,“JS逻辑层”不是浏览器环境,自然没有cookie,所以通常使用访问令牌的方法。
2.2关于需要用户昵称、手机号码等进一步信息的产品的“授权”。出于用户隐私考虑,微信需要用户主动同意授权。只有小程序才能获取这些信息,于是就有了现在流行的小程序“授权用户信息”和“授权手机号”的交互。
由于不同用户的信息敏感度不同,微信小程序对不同用户的信息以不同的方式提供“授权”:
调用特定API模式,弹出授权。比如调用wx.getLocation()时,如果用户没有被授权,就会弹出地址授权界面。如果被拒绝,就不会再弹出,wx.getLocation()直接返回失败。& lt按钮打开-type = & quot;xxx & quot& gt& lt/button & gt;方式。仅支持:用户的敏感信息和用户的手机号需要和后端对称加密解密才能得到数据。用户拒绝了。再次点击按钮仍会弹出窗口。通过wx.authorize()提前请求授权,之后需要获取相关信息时就不用再弹出授权了。四。详细设计理清概念后,我们的模块可以分为两块:
登录:负责与服务器建立会话,实现静默登录及相关容错处理等。模块命名为:会话授权:负责与用户交互,获取和更新信息,控制权限的处理等。该模块命名为:登录3.1.1静默登录的Auth3.1实现
微信提供的官方登录方案总结为三个步骤:
前端通过wx.login()获取一次性加密凭证码,交给后端。后端将这个代码传输到微信服务器,换取用户的唯一标识符openId和授权证书session_key。(后续服务器和微信服务器的特殊API调用,具体见:微信公文-服务器获取开放数据)。后端将从微信服务器获取的用户凭证和自己生成的登录状态令牌发送给前端。前端保存下来,在下一次请求的时候带到后端,这样就可以识别哪个用户了。如果你只是实现这个过程,那就相当简单了。
但是为了实现健壮的登录过程,我们需要注意更多的边界条件:
调用折叠wx.login():
因为wx.login()会产生不可预知的副作用,比如session_key失效,导致后续授权解密场景失败。我们可以在这里提供一个类似session.login()的方法,掌握wx.login()的控制权,对其做一系列的封装和容错处理。
通话时间:
通常,我们会在应用程序启动时启动静默登录(app.onLaunch())。但是,小程序的生命周期设计会产生一个异步问题:当加载一个页面,调用一个需要登录状态的后端API时,可能无法完成之前的异步静态登录过程,导致请求失败。
当然,登录调用也可以在需要登录状态的第一个接口调用时以异步阻塞的方式发起,这需要结合一个设计良好的接口层。
下面将讨论上述两种场景的详细设计思路。
并发调用的问题:
在业务场景中,难免会有多个代码需要触发登录。如果出现极端情况,这些代码会同时被调用。这将导致在短时间内多次启动登录过程,即使之前的请求尚未完成。针对这种情况,我们可以把第一次调用当做阻塞,后续调用等待结果,就像精卵结合的过程一样。
未过期呼叫的问题:
如果我们的登录状态没有过期,可以正常使用,默认不需要发起登录流程。这个时候我们可以默认检查登录状态是否可用,然后我们提出一个请求。然后,您可以提供一个类似session.login({ force: true})的参数来强制启动登录。
3.1.2静默登录异步状态的处理1。当应用程序启动时调用。
因为大多数情况下需要依赖登录状态,所以在应用启动的时候我们会很自然的想到这个时候调用(app.onLaunch())。
但是由于原生小程序启动过程,app、页面、组件的生命周期钩子函数不支持异步阻塞。
那么我们就很容易遇到,app发起的“登录过程”。在page.onLoad的时候onload还没有完成,所以我们不能正确的做一些依赖于登录状态的操作。
针对这种情况,我们设计了一个状态机的工具:status。
基于状态机,我们可以编写这样的代码:
从“@beautywe/plugin-status”导入{ Status };//on app . jsapp({ Status:{ log in:new Status(' log in ');},onLaunch() {session //发起静默登录调用。login() //将状态机设置为成功。然后(()= & gtThis.status.login.success()) //将状态机设置为失败。catch(()= & gt;this . status . log in . fail());},});//on page . jspage({ onLoad(){ const loginStatus = getApp(). status . log in;// must会判断状态,比如登录时等待,登录成功直接返回,登录失败抛出。log in status()status . log in . must(()= & gt;{//执行一些需要登录状态的操作...});},});复制代码2。当调用“第一个需要登录的接口”时,发起登录。
此外,我们会发现,需要登录状态的更深层节点是在需要登录状态的后端API启动时启动的。
然后我们就可以在调用“后台API要求登录状态”的时候启动“静默登录”。对于并发场景,只需让其他请求等待。
以fly.js作为wx.request()封装的“网络请求层”,做一个简单的例子:
//发起请求,并表明请求是fly.post ('https://... ',params,{needlogin: true}),需要登录。//处理逻辑fly . interceptors . request . use(async(req)= > {//if(req . need log in!= = false){//确保登录的核心逻辑是:判断是否已经登录,如果没有,发起登录调用,如果正在登录,进入队列等待回调。await session . ensurelog in();//登录成功后,获取令牌,通过headers传递给后端。const token = await session . gettoken();Object.assign(req.headers,{
Session_key时效性强,以下摘自微信官方描述:
session key session_key的有效性如果开发者因为session_key不正确而遇到签名验证或解密失败的情况,请注意以下与session_key相关的注意事项。
调用wx.login时,可能会更新用户的session_key,使旧的session_key失效(刷新机制的周期最短,如果同一用户在短时间内多次调用wx.login,并不是每次调用都会导致session_key刷新)。开发者应该在明确需要重新登录的情况下才调用wx.login,并及时通过auth.code2Session接口更新服务器中存储的session_key。微信不会通知开发者session_key的有效期。我们会根据用户使用小程序的行为来更新session_key。用户使用小程序越频繁,session_key的有效期越长。当session_key无效时,开发者可以通过重新执行登录过程来获得有效的session_key。接口wx.checkSession可以用来检查session_key是否有效,从而避免小程序重复执行登录过程。开发者在实现自定义登录状态时,可以考虑将session_key的有效期作为自己登录状态的有效期,也可以实现自定义时效性策略。翻译成两个简单的句子:
session_key的时效性是微信控制的,开发者不可预知。Wx.login可能会导致session_key过期。在使用该接口之前,可以使用wx.checkSession对其进行检查。对于第二点,我们通过实验发现,偶尔session_key过期时,wx.checkSession在概率上会返回true。
社区也有尚未解决的相关反馈:
小程序解密手机号码。过了一小段时间,checksession:ok,但是解密失败。wx.checkSession有效,但解密数据失败。Check session判断session_key不是无效,而是手机号解密失败,所以结论是wx.checkSession的可靠性没有达到100%。
基于以上,我们需要对session_key的到期做一些容错处理:
在启动需要session_key的请求之前,请执行一次wx.checkSession操作,如果失败,请刷新登录状态。后端使用session_key解密开放数据失败后,返回特定错误代码(如DECRYPT_WX_OPEN_DATA_FAIL),前端刷新登录状态。示例代码:
//定义检查session_key有效性的操作。Constance session key = async()= > { const has session = wait new Promise(resolve = & gt;{ wx . check session({ success:()= & gt;resolve(true),fail:()= & gt;resolve(false),});});如果(!has session){ logger . info(' session key过期,刷新登录状态');//连接上面提到的刷新登录逻辑,返回session . refresh log in();} return promise . resolve();}//发出请求时,先做操作保证最新的session_key(以fly.js为网络请求层为例)。const Update Phone = async(params)= > { await ensuresession key();const RES = await fly . post(' https://XXX ',params);}//添加一个响应拦截器来监听网络请求并返回fly。interceptors . response . use((response)= > { const code = RES . data;//如果登录状态过期或无效(
那么授权阶段可以分为三层:
//阶段用户登录导出enum AuthStep {//阶段1:只有登录状态,没有用户信息,没有手机号ONE = 1,//阶段2:用户信息,没有手机号TWO = 2,//阶段3:用户信息,手机号THREE = 3,}复制AuthStep的过程是不可逆的,我们可以定义一个nextStep函数,外用,只要没有大脑调用nextStep方法,等待回调结果。
示例伪代码:
//auth-flowcomponent组件({//...数据:{//默认只需要达到第二阶段。MustAuthStep: AuthStep。TWO }、//允许对组件的所需阶段进行临时更改。setMustAuthStep(mustAuthStep:auth step){ this . setdata({ mustAuthStep });},//根据用户当前的信息,计算出用户处于授权阶段getAuthStep(){ let curr authstep;//没有用户信息,仍在第一步if(!session.hasUser() ||!session . hasunionid()){ currAuthStep = AuthStepType。一;}//没有手机号,还在第二步如果(!session . has phone()){ currAuthStep = AuthStepType。二;}//both,还在第三步currauthstep = authsteptype。三;返回currAuthStep}//发起下一步授权,完成直接返回成功。next step(e){ const { mustAuthStep } = this . data;const curr authstep = this . updateauthstep();//授权if(curr auth step >;= mustauthstep | | | curr authstep = = authsteptype。三){//更新全局授权状态机并将消息广播给订阅者。返回getApp()status . auth . success();}//第一步:更新用户信息if (currauthstep = = = authsteptype。one){//已有密文信息,更新用户信息if(e)session . update user(e);//更新到视图层,显示对应的UI,等待用户信息else this . setdata({ curr auth step });返回;}//第二步:更新手机信息if (currauthstep = = = authsteptype。two){//已有密文信息,更新手机号if(e)this . bind phone(e);//没有密文信息,弹出采集窗口else this . setdata({ curr auth step });返回;} console . warn(' auth . next step error ',{currAuthStep,mustAuthStep });}, // ...});复制代码,然后我们的
示例伪代码:
& lt视图& gt& lt!--授权完成--& gt;& ltblock & gt& lt视图& gt授权完成
我们整理出需要授权的场景:
例如,点击一个按钮,购买一件商品。
对于这种情况,通常通过弹出窗口完成授权,用户可以选择关闭它。
浏览网页,例如,访问个人中心。
对于这个场景,我们可以在点击跳转到页面时截取并弹出一个窗口。但缺点是可能会有很多地方跳转到目标页面,每一个都会被截取,难免会出现错漏。而当目标页面作为“小程序登陆页面”时,也是无法避免的。
这时,我们可以通过重定向到授权页面来完成授权过程,然后再回来。
然后我们定义一个枚举变量:
//导出授权的enumauth显示方式{//Pop-up =' button '以弹出的形式,//Page =' page '以页面的形式,}我们可以设计一个mustAuth方法来控制点击按钮或者加载页面时的授权。
伪代码示例:
ClassSession {/...must hauth({ mustauthstep = authsteptype。二、//需要授权的级别,默认需要用户数据popupCompName = 'auth-popup '。//授权弹出组件的ID模式= authdisplaymode。popup,//默认弹出模式} = { }):Promise & lt;= mustAuthStep)return promise . resolve();//尝试获取
以静默方式登录到silentLogin。
参数输入:code: from wx.login()参数输出:token:用户信息描述:后端用代码与微信客户端交换用户ID,然后注册登录用户,将自定义的登录令牌返回给前端token,这个令牌会存储在前端,每个请求都会包含包括昵称、电话等userInfo字段,前端用来计算当前用户的授权阶段。当然这种状态的记录可以放在后端,但是我们觉得放在前端会更灵活。更新用户信息更新用户
输入:昵称:用户昵称:encrypt:与微信开放数据相关的IV、encryptedData等不必要的字段如性别地址:userInfo:更新的最新用户信息描述:后端解密微信开放数据,获取隐藏数据。比如后端支持更新包括昵称在内的用户基本信息。前端将userInfo信息更新到用于计算授权阶段的会话。更新用户的手机号码更新电话
入口:encrypt:与微信开放数据相关的IV,出口:userInfo:更新的最新用户信息描述:后端解密开放的office,获取手机号,更新为用户信息。前端将userInfo信息更新到用于计算授权阶段的会话。解除手机号码绑定解除手机绑定
入口:-出口:-描述:后端解绑用户手机号,无论成功与否,都遵循服务定义的前端协议。登录注销
参与人数:3人以上
参与人数:3人以上
描述:后端主动过期登录状态,无论成功与否,都遵循业务定义的前端协议。
动词 (verb的缩写)架构图最后,我们来梳理一下整体“注册服务”的架构图:
对于“登录服务”和“基础设施”组合提供的常用服务,业务层只需要根据产品需求定制授权流程< auth -flow & gt;& lt/auth -flow & gt;,可以满足大部分场景。
不及物动词摘要本文通过一些常见的登录授权场景来描述细节。
梳理了“登录”和“授权”的概念。
然后,介绍了“登录”的一些关键技术:
静默登录静默登录异步状态处理自定义登录状态过期容错处理微信session_key过期容错处理对于“授权”,会有设计UI部分的逻辑,还需要涉及组件拆分:
然后整理了这个登录授权方案所依赖的后端接口,并给出了最简单的参考协议。
最后,本文从“旨在解决一套通用的小程序登录方案和服务”的角度,梳理了架构层面的分层。
业务定制层登录服务层底层建设微信app下载微信是一款手机通讯软件,支持通过手机网络发送语音消息、视频、图片、文字。微信可以单独聊天,也可以群聊,根据地理位置找到附近的人,带给你全新的移动通信体验。快来拯救下载体验给有需要的朋友吧!
下载
这几篇文章你可能也喜欢:
本文由主机参考刊发,转载请注明:了解微信小程序登录的前端设计和实现(微信小程序登录后端) https://zhujicankao.com/121028.html
评论前必须登录!
注册