热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

微信小程序静默登录和维护自定义登录态详解

这篇文章主要给大家介绍了关于微信小程序静默登录和维护自定义登录态的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1.背景

在小程序中,openid是一个用户对于一个小程序/公众号的标识,开发者可以通过这个标识识别出用户,就如同你的身份证一样。

2.什么是静默登录?

在普通的应用中,用户通过表单验证登录建立用户体系,这种常见的登录方式一般是通过登录页面表单进行登录,对用户来说是有感的。

在小程序中,由于是基于微信,可以通过微信官方提供的API能力,使我们能够无感知得获取用户身份标识(openid),快速建立小程序内的用户体系,对用户来说是无感知的,因此是由程序来完成这个自动的登陆过程。

2.1登录流程时序

下图取自微信官方

小程序端调用wx.login(),获取code并且上传到服务器

export async function doLogin() {
 if (isLogin) return false
 isLogin = true
 removeCache('token')
 const { code } = await wxp.login()
 const data = await login({ code })
 setCache('token', data.data.token)
 isLogin = false
 return true
}

服务端拿到code,调用auth.code2Session接口换取openid
const getOpenid = async function (appid, secret, code) {
    const resData = await axios.get('https://api.weixin.qq.com/sns/jscode2session?appid=' + appid + '&secret=' + secret + '&js_code=' + code + '&grant_type=authorization_code');
    return resData.data;
}

总结流程:

  • 小程序端调用wx.login(),获取code并且上传到服务器
  • 服务器根据code,并且调用微信auth.code2Session接口换取openid
  • 后台服务器根据openid生成自定义token返回前端并且存储起来,后续业务逻辑用token来识别用户身份

3.如何维护自定义登录态

让我们来看下官方的处理方式:

wx.checkSession({
  success () {
    //session_key 未过期,并且在本生命周期一直有效
  },
  fail () {
    // session_key 已经失效,需要重新执行登录流程
    wx.login() //重新登录
  }
})

由图中我们可以知道,真正决定登录态的是微信的checkSession接口。因此每次检查用户登录态是否有效就先调用一个checkSession接口,如果session_key失效,再发起登录流程。

4.静默登录整体流程

4.1app.onLaunch中发起登录

由于大部分的接口调用都需要token验证,因此在小程序启动的周期函数app.onLaunch中发起静默登录最为合适不过了。

4.2处理小程序不支持异步阻塞

由于小程序的启动流程中,页面级和组件级的生命周期函数都不支持异步阻塞;因此会造成一个情况,app.onLaunch中发起的wx.login还没有成功的时候,页面级的生命周期函数已经向服务器发起请求。由于我们的接口设计大部分都是需要验证的,此时登录还未成功,token也还没有正确返回,因此页面级的生命周期发起的数据获取接口肯定是会报错的(例如返回了401)

4.2.1粗糙的方案

采用回调函数的方式

//app.js
this.globalData.wxp.showLoading({
        title: '登录中...'
      });
      await login();
      this.globalData.hasLogin = true;
      if (this.checkLoginReadyCallback) {
        this.checkLoginReadyCallback();
      }
      this.globalData.wxp.hideLoading();
      
页面的生命周期中
async onLoad() {
    if (app.globalData.hasLogin) {
    //如果已经登录了直接获取数据
      this.getUserInfo();
      this.getEvent();
    } else {
    //未登录定义下回调函数,等app.js登录成功之后进行调用
      app.checkLoginReadyCallback = async () => {
        this.getUserInfo();
        this.getEvent();
      };
    }
  },

优点:简单粗暴

缺点:代码结构差;如果是多个页面为启动页,则需要多个页面都定义回调函数(假设使用了小程序onShare模式)

4.2.2优雅的方式

借助fly.js库,实现对请求进行上锁机制。流程:app.js中发起登录,同时页面中也会发起请求。在请求拦截器中判断请求的接口是否为白名单(不需要token验证的接口)接口和token是否存在;如果都为false,锁住当前请求进入请求队列,执行登录流程。等待登录流程成功之后解锁请求队列,继续发起页面级的请求任务。如下为请求拦截器中的代码:

//拦截处理
fly.interceptors.request.use(async (request) => {
	//没有token且请求不是白名单的都锁住
	if (
		!getCache('token') &&
		!whiteList.some((item) => request.url.startsWith(item))
	) {
		fly.lock()
		//去登陆 成功之后再unlock
		await doLogin()
		fly.unlock() //解锁后,会继续发起请求队列中的任务
	}

	if (getCache('token') && !fly.config.headers['Authorization']) {
		request.headers['Authorization'] = getCache('token')
	}
	request.headers['Content-Type'] = 'application/x-www-form-urlencoded'

	return request
})

当然,自定义登录态也会存在过期的情况,我们可以在响应拦截器中捕获出错进行处理:当检测到401token过期代码时,需要把请求队列后面的请求都锁死,防止多次出现401自定义登录态过期的情况,然后发起登录,登陆成功之后再进行解锁行为,触发后续的请求队列执行,并且重新执行本次由于token过期被服务器拒绝的接口,否则会造成请求失败的情况(由于静默登录是用户无感知的,突然出现身份验证信息过期会使用户感觉到特别地奇怪,因此需要重新执行本次请求操作而不是由用户再次点击或者其他的行为再发起):

// 响应拦截
fly.interceptors.response.use(
	(response) => {
		//只将请求结果的data字段返回
		return response.data
	},
	async (err) => {
		if (err.status === 401) {
			//401之后,把后面的请求都锁死 防止再次401
			fly.lock()
			removeCache('token')
			//去登陆 成功之后再unlock
			const isLoginSuccess = await doLogin()
			if (isLoginSuccess) {
				fly.unlock()
			}
                        //新执行本次由于token过期被服务器拒绝的接口
			return fly.request(err.request)
		}
	}
)

由于请求有可能是并发的,为了防止登录被多次执行,因此对doLogin函数进行了小小的改造(尽管写得很不优雅,但是能力有限,大佬们赐教了):

export async function doLogin() {
        //如果正在登录中则不执行
	if (isLogin) return false
	isLogin = true
        //修改状态为登录中,反正重复多次登录
	removeCache('token')
	const { code } = await wxp.login()
	const data = await login({ code })
	setCache('token', data.data.token)
	isLogin = false
	return true
}

4.3 整体流程图

5.写在最后

细节的读者即可发现,api请求中并未设置最大请求数量的(微信小程序最大支持五个api同时发起),这点是需要补充进来的。总体写下来作者觉得在实现方式上还有进步的空间,作者能力有限,也是一边学习一边探讨!

到此这篇关于微信小程序静默登录和维护自定义登录态的文章就介绍到这了,更多相关微信小程序静默登录内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!


推荐阅读
  • 本文详细介绍了网络存储技术的基本概念、分类及应用场景。通过分析直连式存储(DAS)、网络附加存储(NAS)和存储区域网络(SAN)的特点,帮助读者理解不同存储方式的优势与局限性。 ... [详细]
  • 本文介绍了如何使用PHP代码实现微信平台的媒体素材上传功能,详细解释了API接口的使用方法和注意事项,确保文件路径正确以避免常见的错误。 ... [详细]
  • 从零开始构建完整手机站:Vue CLI 3 实战指南(第一部分)
    本系列教程将引导您使用 Vue CLI 3 构建一个功能齐全的移动应用。我们将深入探讨项目中涉及的每一个知识点,并确保这些内容与实际工作中的需求紧密结合。 ... [详细]
  • 本文将深入探讨PHP编程语言的基本概念,并解释PHP概念股的含义。通过详细解析,帮助读者理解PHP在Web开发和股票市场中的重要性。 ... [详细]
  • 阿里宝卡用户能否在UC浏览器极速版中享受免流量服务?
    本文详细介绍了UC浏览器极速版是否支持阿里宝卡的免流量功能,以及如何正确设置以确保免流量服务的正常使用。 ... [详细]
  • 使用JS、HTML5和C3创建自定义弹出窗口
    本文介绍如何结合JavaScript、HTML5和C3.js来实现一个功能丰富的自定义弹出窗口。通过具体的代码示例,详细讲解了实现过程中的关键步骤和技术要点。 ... [详细]
  • 本文介绍了如何在具备多个IP地址的FTP服务器环境中,通过动态地址端口复用和地址转换技术优化网络配置。重点讨论了2Mb/s DDN专线连接、Cisco 2611路由器及内部网络地址规划。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 尽管某些细分市场如WAN优化表现不佳,但全球运营商路由器和交换机市场持续增长。根据最新研究,该市场预计在2023年达到202亿美元的规模。 ... [详细]
  • 解决微信电脑版无法刷朋友圈问题:使用安卓远程投屏方案
    在工作期间想要浏览微信和朋友圈却不太方便?虽然微信电脑版目前不支持直接刷朋友圈,但通过远程投屏技术,可以轻松实现在电脑上操作安卓设备的功能。 ... [详细]
  • 本文探讨了将类成员属性设置为私有的重要性,并通过具体代码示例展示了如何实现对这些属性的有效控制。私有成员属性有助于增强数据的安全性和完整性,确保只有经过验证的数据才能被修改。 ... [详细]
  • 深入解析TCP/IP五层协议
    本文详细介绍了TCP/IP五层协议模型,包括物理层、数据链路层、网络层、传输层和应用层。每层的功能及其相互关系将被逐一解释,帮助读者理解互联网通信的原理。此外,还特别讨论了UDP和TCP协议的特点以及三次握手、四次挥手的过程。 ... [详细]
  • 本文探讨了在使用 Ajax 发送请求时,安卓浏览器出现的重复请求问题。该问题仅出现在安卓设备上,而 iOS 和 PC 端均无此现象。具体表现为服务端接收到多个重复的请求,导致操作逻辑混乱。 ... [详细]
  • 本文详细介绍Python编程的基础知识,涵盖从安装环境到编写简单程序的核心内容,并深入探讨网络编程的基本概念和实践。提供多种资源下载方式,帮助读者快速上手。 ... [详细]
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
author-avatar
张火蓉景荣馨季
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有