小程序用户登录架构设计,顺利通过阿里面试

| login | 登录,silentLogin方法的一层封装 | 用于小程序启动时发起静默登录 |

| refreshLogin | 刷新登录态,silentLogin方法的一层封装 | 用于登录态过期时发起静默登录 |

| ensureSessionKey | 验证sessionKey是否过期,过期则刷新登录态 | 绑定微信授权手机号时验证是否过期,过期则得重新弹窗授权 |

| bindPhone | 绑定微信授权手机号 | 微信授权手机号弹窗点击「允许」触发 |

| updateUser | 绑定微信授权用户信息 | 微信授权用户信息点击「允许」触发 |

| getCurrentAuthStep | 获取当前用户登录所属阶段 | 详见下文 |

| mustAuth | 各种触发场景拦截判断是否需要登录 | 详见下文 |

当然,session类中还封装了一些方法用于与storage交互,比如获取storage中的auth-token用于各种鉴权请求携带等等。session类也提供的一些拓展方法,比如注销账号、解绑手机号等等用于后续需求迭代。

  1. 装饰器:
  • must-authmustAuth类方法的装饰器,便于业务层各种场景触发登录。

  • fuse-line熔断机制,如果短时间内多次调用,则停止响应一段时间,类似于 TCP 慢启动。用于解决refreshLoginlogin等方法的并发处理问题。

  • single-queue单队列模式,同一时间,只允许一个正在过程中的网络请求。请求被锁定之后,同样的请求都会被推入队列,等待进行中的请求返回后,消费同一个结果。用于解决refreshLoginlogin等方法的并发处理问题。

3.1.2 ui - 提供通用组件供业务层调用

  1. 基础组件user-containerphone-container分别是获取「微信授权用户信息」和获取「微信授权手机号」的纯 UI 单元组件,给通用组件使用。

  2. behavior 类:拿到授权数据后需要发送给服务端进行存储,也需要执行一些跳转逻辑判断,这些都抽象成行为类封装在auth-flow中,供通用组件使用。

  3. 通用组件:共用一个行为类,区别在于auth-flow-container用于页面,auth-flow-popup用于弹窗。如下所示,小程序只有微信授权功能,则可以通过弹窗完成授权。如小程序同时提供手机号验证码和密码登录等功能,则需跳转特定登录页面。

登录流程-弹窗

3.2 libs


3.2.1 用户身份定义

用户登录阶段

综上所示,用户登录的阶段可以分为以下三步:

// 用户登录的阶段

export enum AuthStepType {

// 阶段一:游客态:静默登录成功,未绑定手机号,无用户信息

ONE = 1,

// 阶段二:会员态:用户登录成功,已绑定手机号,无用户信息

TWO = 2,

// 阶段三:会员信息态:用户登录成功,已绑定手机号,有用户信息

THREE = 3,

}

那么如何判断用户此时处于哪个步骤,基于「静默登录」的启发,原本「静默登录」成功开发者后端会将自定义登录态 auth-token返回给前端,此处请求可以携带返回「用户信息」,同auth-token一起命名为session存储在本地storage当「用户登录」或者「更新用户信息」时,会同步更新storagekeysession的数据,从而通过这些用户数据判断当前用户处于哪一个登录阶段

以下表格列出了session存储的部分重要的属性以及在三个阶段属性对应的值。

| 属性 | 定义 | 游客态 | 会员态 | 会员信息态 |

| — | — | — | — | — |

| authToken | 自定义登录态 | ‘0d5bad172…’ | ‘0d5bad172…’ | ‘0d5bad172…’ |

| uid | 用户 id | ‘001’ | ‘001’ | ‘001’ |

| busiIdentity | 用户身份定义 | ‘VISIT’ | ‘MEMBER’ | ‘MEMBER’ |

| nickName | 用户昵称 | ‘’ | ‘u_a1bk45’ | ‘rileycai’ |

| headUrl | 头像链接 | ‘’ | ‘’ | ‘www.xx.com/image/…’ |

| phone | 手机号码 | ‘’ | ‘17600888888’ | ‘17600888888’ |

| … | 其它用户信息 | … | … | … |

注意: 会员态和会员信息态的busiIdentity值均为MEMBER,区分会员态和会员信息态可以通过用户昵称和头像等字段,比如用户登录成功会为用户生成以’u_'开头的默认昵称和默认为空的用户头像链接。

判断用户此时处于哪个步骤的代码如下:

// 获取当前授权阶段

public getCurrentAuthStep(): AuthStepType {

// 切换账号登录的时候,始终返回AuthStepType.ONE

const loginMode = this.getLoginMode();

if (loginMode === LoginMode.SWITCH_ACCOUNT) return AuthStepType.ONE;

// 用户身份定义非会员返回AuthStepType.ONE

const userInfo = this.getUser();

if (userInfo?.busiIdentity !== ‘MEMBER’) return AuthStepType.ONE;

// 初次登录,未授权用户信息,返回AuthStepType.TWO

if (userInfo.nickName.substring(0, 2) === ‘u_’ && !userInfo.headUrl)

return AuthStepType.TWO;

// 都有,返回AuthStepType.THREE

return AuthStepType.THREE;

}

3.2.2 用户登录触发场景

前面提到过,「用户登录」的 目的是为了整合各个渠道的交易、促销、收藏等数据,针对电商小程序,目前总结的需要用户登录的场景如下所示:

用户登录场景

即当用户登录小程序时,可以正常浏览浏览商品,只有触发某些特定行为,比如领券、加购、收藏、下单等,才会判断用户是否处于登录状态,如未登录,跳转登录页面

如下所示,封装mustAuth方法进行拦截,未登录则跳转登录页面:

export default class Session {

public mustAuth({

mustAuthStep = AuthStepType.TWO, // 传人参数,需要授权的LEVEL

} = {}): Promise {

// 当前阶段处于会员态(2)或者会员信息态(3),执行resolve操作

if (this.getCurrentAuthStep() >= mustAuthStep) return Promise.resolve();

// 当前阶段处于游客态(1),跳转登录页

Navigator.gotoPage(‘/login/home’);

// 执行reject操作

return Promise.reject();

}

}

上述代码是跳转页面拦截,对于弹窗而言,需要把弹窗注入base-page(每个页面都需要引入的通用组件,封装每个页面都需要使用的通用方法,比如错误处理等)中,通过 id 查找到弹窗组件,并进行调用。

export default class Session {

public mustAuth({

mustAuthStep = AuthStepType.TWO, // 需要授权的LEVEL

popupCompName = ‘auth-flow-popup’,

} = {}): Promise {

// 当前阶段处于会员态(2)或者会员信息态(3),执行resolve操作

if (this.getCurrentAuthStep() >= mustAuthStep) return Promise.resolve();

// 获取弹窗组件

const pages = getCurrentPages();

const curPage = pages[pages.length - 1];

const context = curPage.$$basePage || curPage;

const popupComp = context.selectComponent(#${popupCompName});

// 容错处理

if (!popupComp) {

return Promise.reject(

new Error(

“当前页面未找到 #auth-popup 组件,请参考 ‘doc/登录组件的使用方式.md’”,

),

);

}

// 调用弹窗组件方法

popupComp.setMustAuthStep(mustAuthStep);

popupComp.nextStep();

// 等待授权成功回调

return this.waitAuth();

}

}

各个业务使用时可以通过session.mustAuth().then(() => {...});进行调用,为了提高使用体验,也可以使用装饰器@mustAuth()来修饰各个业务需求 类的方法,装饰器源码如下:

/**

* 登录检查装饰器,使用该装饰器的方法,会先执行授权检查,如果未授权,将跳转登录页面

*/

export default function mustAuth(option = {}) {

return function(

_target: Record<string, any>,

_propertyName: string,

descriptor: TypedPropertyDescriptor<(…args: any[]) => any>,

) {

const method = descriptor.value;

descriptor.value = function(…args: any[]) {

if (!session) return;

// 登录拦截

return session.mustAuth(option).then(() => {

if (method) return method.apply(this, args);

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
img

最后

技术是没有终点的,也是学不完的,最重要的是活着、不秃。零基础入门的时候看书还是看视频,我觉得成年人,何必做选择题呢,两个都要。喜欢看书就看书,喜欢看视频就看视频。最重要的是在自学的过程中,一定不要眼高手低,要实战,把学到的技术投入到项目当中,解决问题,之后进一步锤炼自己的技术。

技术学到手后,就要开始准备面试了,找工作的时候一定要好好准备简历,毕竟简历是找工作的敲门砖,还有就是要多做面试题,复习巩固。

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img

的,最重要的是活着、不秃。零基础入门的时候看书还是看视频,我觉得成年人,何必做选择题呢,两个都要。喜欢看书就看书,喜欢看视频就看视频。最重要的是在自学的过程中,一定不要眼高手低,要实战,把学到的技术投入到项目当中,解决问题,之后进一步锤炼自己的技术。

技术学到手后,就要开始准备面试了,找工作的时候一定要好好准备简历,毕竟简历是找工作的敲门砖,还有就是要多做面试题,复习巩固。

[外链图片转存中…(img-xmi0slJg-1712577782539)]

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-HFjny0My-1712577782539)]

  • 13
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值