2024年前端最全小程序用户登录架构设计(1),2024年最新面试技巧全套教程

对象篇

模块化编程-自研模块加载器

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

| 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);

});

};

};

}

3.3 UI


3.3.1 基础组件

1. phone-container 组件

因为需要用户主动触发才能发起获取微信授权手机号接口,需用 button 组件的点击来触发。组件代码如下所示:

// index.wxml

// index.ts

export default class PhoneContainer extends BaseComponent {

getPhoneNumber(

e: WechatMiniprogram.Event<WechatMiniprogram.GetPhoneNumberCallbackResult>,

) {

this.triggerEvent(‘getphonenumber’, { …e.detail,  authType: AuthType.PHONE,});

}

}

phone-container是一个纯 UI 组件,通过triggerEvent事件将获取手机号数据传递给父组件,

2. user-container 组件

user-container组件是获取微信授权用户信息的纯 UI 组件,之前通过<button open-type="getUserInfo" bindgetUserInfo="getUserInfo"/>的方式进行获取。2021 年 2 月 23 日,微信团队发布了《小程序登录、用户信息相关接口调整说明》,新增getUserProfile接口替代原来的wx.getUserInfo,来获取用户头像、昵称、性别及地区信息,也是通过button 组件的点击来触发。两者的区别如下图所示:

获取用户信息接口区别

2012 年 4 月 13 日之前,使用wx.getUserInfo弹出授权弹窗时,如果用户点击允许授权,那么会记录用户的行为,下次再点击时,不会弹窗而是直接将授权结果返回。4 月 13 日之后后,使用wx.getUserProfile开发者每次通过该接口获取用户个人信息均需用户确认,因此需要妥善保管用户授权的头像昵称,避免重复弹窗。

3.3.2 行为类

如下图所示,auth-flow行为类主要封装用户、小程序、服务端三者之间的交互逻辑。

用户行为

在「微信授权登录」过程中,小程序拿到加密的encryptedDataiv数据,将其和携带的auth-token一起发送给开发者服务器,服务端通过auth-token鉴权识别这个用户,并使用静默登录成功获取的session_key(对称解密密钥)对encryptedDataiv数据进行对称解密,获取该用户的手机号,将手机号与uid绑定,此时该用户成功注册会员,并将会员信息返回给小程序端。

小程序端更新本地storage存储的session数据,此时busiIdentity的值已经从VISIT更新为MEMBER,用户身份转变为会员态,登录成功。

在「授权用户信息」的过程中,小程序调用wx.getUserProfile方法拿到用户数据,并将这些数据与携带的auth-token一起发送给开发者服务器,服务端通过auth-token鉴权识别这个用户,更新该用户的信息并将新的会员数据返回给小程序端。

小程序端更新本地storage存储的session数据,此时用户昵称和头像均已更新,用户身份转变为会员信息态,授权成功。

眼尖的读者一定观察到了,时序图中还对微信头像做了转存。这是因为用户在微信端修改微信头像后,之前「授权用户信息」获取的微信头像链接就会失效,因此开发者应该在自己获取用户信息后,将头像保存下来,避免微信头像 URL 失效后的异常情况。

3.3.3 通用组件

通用组件是对基础组件和行为类的二次封装,主要是为业务层提供弹窗登录和页面登录两种能力。

4. 总结


我们将用户登录能力从业务层中抽象出来,统一封装在service层,便于复用。本文主要讲述的是service层的架构,对于业务层的逻辑实现并没有多加累赘。下列表格以小程序端为例,简述了「静默登录」和「用户登录」整套方案的前后端逻辑实现。

| 业务场景 | 用户感知 | 前端处理逻辑 | 后端处理逻辑 | 补充说明 |

| — | — | — | — | — |

| 扫码搜索等各种方式进入小程序 | 无 | 1、判断:当前小程序是否缓存了登录态auth-token 且使用wx.checkSeesion检查当前用户在小程序中登录态是否过期,过期执行步骤 2; |

|

|

| 2、使用wx.login获取认证信息,请求后端wxLogin接口获取微信小程序认证默认绑定的用户身份以及登录态auth-token。 | 1、解析微信加密信息获取认证身份openidunionId; |

|

|

|

2、查找openid是否已经绑定了对应的用户,若绑定直接返回并为其生成对应的登录态auth-token

3、新用户会根据openid为其自动生成一个用户身份uid(见右补充说明)。| a、存在聚合根标识unionId && 有用户信息:将已有聚合根用户对应的exUid直接映射到当前uid下;

b、存在聚合根标识unionId && 无用户信息:根据unionId生成对应的账号,但和opneid对应的uid一致;

c、不存在聚合根标识:直接为对应openid初始化一个uid。| | 收藏加购下单领券等操作 | 拦截跳转 | 1、判断:当前用户身份处于游客态,跳转登录页面。| 对应域服务后端接口可以根据请求携带的auth-token进行鉴权,判断用户是否有操作权限 | - | | 用户登录 或者 切换账号 | 选择:

1、授权微信手机号登录;

2、输入手机号并使用验证码/密码登录 | 1、用户选择授权手机号登录,后端会根据上一次静默登录的sesssionKey解密,如果解密失败需要重新走一遍静默登录后再让客户重试。

2、用户选择通过验证码登录时,需关注验证码时效和重试机制,并有错误处理逻辑;

3、用户选择密码登录时,后台会返回账户未注册或账号密码不对等错误,需要有独立逻辑跳转验证码注册或找回密码

4、以上三种方式都需要携带auth-token进行鉴权 | 1、根据auth-token获取当前的渠道基本认证账户openid-unionId-uid

2、授权手机号登录时需要先解密出手机号,此时不需要校验,输入手机号登录时需要会走「密码」或「验证码」校验,密码校验会拦截账号不存在或密码错误的场景;

3、根据手机号判断当前聚合根下是否存在对应的手机号渠道账号(绑定流程见右补充说明)。

4、返回登录结果。| a、手机号已存在:将已存在的用户exUid绑定至当前登录态账号;

b、手机号不存在 && 用户身份是游客:将手机号和游客对应的uid进行绑定

c、手机号不存在 && 用户身份是会员:为手机号生成一个新的newUid,并将当前登录的 openid 渠道账户绑定至该newUid

作者: 蔡小真

https://juejin.cn/post/6945264484491460638

推荐阅读

小程序如何生成海报分享朋友圈

最后

在面试前我花了三个月时间刷了很多大厂面试题,最近做了一个整理并分类,主要内容包括html,css,JavaScript,ES6,计算机网络,浏览器,工程化,模块化,Node.js,框架,数据结构,性能优化,项目等等。

包含了腾讯、字节跳动、小米、阿里、滴滴、美团、58、拼多多、360、新浪、搜狐等一线互联网公司面试被问到的题目,涵盖了初中级前端技术点。

  • HTML5新特性,语义化

  • 浏览器的标准模式和怪异模式

  • xhtml和html的区别

  • 使用data-的好处

  • meta标签

  • canvas

  • HTML废弃的标签

  • IE6 bug,和一些定位写法

  • css js放置位置和原因

  • 什么是渐进式渲染

  • html模板语言

  • meta viewport原理

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值