当前位置: 首页 > news >正文

【前端开发】小程序无感登录验证

概述

封装的网络请求库,主要用于处理 API 请求并支持自动处理 token 过期 和 token 刷新,适用于需要身份验证的应用场景,特别是在移动端中。

主要功能

  1. 自动附加 Token

在每个请求中自动附加 Authorization 头部,使用存储的 accessToken。如果某个请求不需要 Token,则可以通过设置 isToken: false 来排除。

  1. Token 过期自动刷新
  • 当请求返回提示 accessToken 过期时,自动尝试使用 refreshToken 刷新 accessToken
  • 在刷新过程中,新的请求会被放入一个队列中,等到 refreshToken 成功后再依次重试
  1. 请求重试机制
  • 当 accessToken 刷新成功后,队列中的所有待处理请求都会自动重发
  • 如果 refreshToken 刷新失败,跳转到登录页面,让用户重新登录。
  1. 统一的请求和响应处理
  • 请求的 Content-Type 和 Accept 头部统一设置
  • 统一处理服务器返回的状态码,若返回 200 且不含 ErrType: -10011,则正常返回数据,否则进行相关的错误处理

代码概览

  1. refreshToken 函数
  • 用于发送请求以刷新 accessToken,通过 refreshToken 获取新的 accessToken,并保存在本地
  • 若成功,返回新的 accessToken;若失败,返回错误信息。
  1. request 函数
  • 封装了 uni.request 请求方法,提供了 GET、POST 请求支持。
    检查是否有有效的 accessToken,如果有,自动将其附加到请求头的 Authorization 中
  • 如果请求参数中包含 params,则自动将其转换为查询字符串附加到 URL 中
  • 在请求成功时,判断返回数据的 ErrType 是否为 -10011(表示 accessToken 过期),若过期,则调用 handleTokenExpiration 函数刷新 Token
  1. handleTokenExpiration 函数
  • 处理 accessToken 过期的逻辑,避免在刷新 Token 的过程中发起多次刷新请求
  • 如果当前没有刷新请求正在进行,则调用 refreshToken 函数尝试刷新 Token,并将待重试的请求保存在队列中
  • 如果刷新 Token 成功,则重试队列中的请求,重新发送
  • 如果刷新 Token 失败,清空队列并跳转到登录页面
  1. isRefreshing 和 requestQueue
  • isRefreshing 用于确保只有一个刷新请求在进行,避免并发刷新 Token 的情况
  • requestQueue 用于存储等待 Token 刷新完成后的请求,确保刷新完成后再逐一处理这些请求

工作流程

  • 用户首次登录时,后端会返回 accessToken 和 refreshToken
  • 后续的 API 请求都会自动附带 accessToken
  • 当 accessToken 过期时,后端返回 ErrType: -10011,触发 handleTokenExpiration
  • handleTokenExpiration 检查是否正在进行刷新操作,如果没有,则开始刷新并保存待重试的请求
  • 刷新完成后,重试这些请求,确保请求使用最新的 accessToken

Request.js

import store from "@/store";
import config from "@/common/config";
import { getToken, getRefreshToken, setToken } from "@/common/auth";
import { tansParams } from "@/common/index";let timeout = 10000;
const baseUrl = config.baseUrl;const refreshToken = () => {return new Promise((resolve, reject) => {uni.request({method: "post",url: `${baseUrl}/auth/refresh`,data: { refreshToken: getRefreshToken() },header: { "Content-Type": "application/json" },}).then((response) => {if (response.statusCode === 200 && response.data.accessToken) {setToken(response.data.accessToken);resolve(response.data.accessToken);} else {reject("刷新令牌失败");}}).catch((error) => {reject(error);});});
};const request = (config) => {const isToken = (config.headers || {}).isToken === false;config.header = config.header || {};if (getToken() && !isToken) {config.header["Authorization"] = "Bearer " + getToken();}if (config.params) {let url = config.url + "?" + tansParams(config.params);url = url.slice(0, -1);config.url = url;}config.header["Content-Type"] ="application/x-www-form-urlencoded; charset=UTF-8";config.header["Accept"] = "application/json, text/javascript, */*; q=0.01";return new Promise((resolve, reject) => {uni.request({method: config.method || "get",timeout: config.timeout || timeout,url: config.baseUrl || baseUrl + config.url,data: config.data,header: config.header,dataType: "json",}).then((response) => {if (response.statusCode === 200) {//登录过期if (response.data.ErrType == "-10011") {// Access Token 过期handleTokenExpiration(config, resolve, reject);} else {resolve(response.data);}} else {reject("服务器连接异常");}}).catch((error) => {reject(error);});});
};let isRefreshing = false; // 防止多次刷新
let requestQueue = []; // 队列存储待重试的请求const handleTokenExpiration = (config, resolve, reject) => {if (!isRefreshing) {isRefreshing = true; // 开始刷新refreshToken().then((newToken) => {isRefreshing = false;// 刷新成功后,重试队列中的请求requestQueue.forEach((callback) => callback(newToken));requestQueue = []; // 清空队列// 重新发送当前请求resolve(request({...config,header: {...config.header,Authorization: "Bearer " + newToken,},}));}).catch((error) => {isRefreshing = false;requestQueue = []; // 清空队列// 刷新失败,跳转到登录页面uni.reLaunch({url: "/pages/login",});reject("登录已过期,请重新登录");});} else {// 如果已经在刷新,将请求加入队列requestQueue.push((newToken) => {resolve(request({...config,header: {...config.header,Authorization: "Bearer " + newToken,},}));});}
};export default request;

相关文章:

【前端开发】小程序无感登录验证

概述 封装的网络请求库,主要用于处理 API 请求并支持自动处理 token 过期 和 token 刷新,适用于需要身份验证的应用场景,特别是在移动端中。 主要功能 自动附加 Token 在每个请求中自动附加 Authorization 头部,使用存储的 acces…...

Flink常见面试题

1、Flink 的四大特征(基石) 2、Flink 中都有哪些 Source,哪些 Sink,哪些算子(方法) 预定义Source 基于本地集合的source(Collection-based-source) 基于文件的source(…...

spark同步mysql数据到sqlserver

使用Apache Spark将数据从MySQL同步到SQL Server是一个常见的ETL(Extract, Transform, Load)任务。这里提供一个基本的步骤指南,以及一些代码示例来帮助你完成这项工作。 ### 前提条件 1. **安装Spark**:确保你的环境中已经安装了…...

Python Web 开发:FastAPI 基本概念与应用

Python Web 开发:FastAPI 基本概念与应用 目录 ✨ 1. FastAPI 路由(定义请求路径)🚀 2. HTTP 请求方法(GET、POST、PUT、DELETE)🔑 3. 参数类型(路径参数、查询参数、请求体&#…...

Linux设置开启启动脚本

1.问题 每次启动虚拟机需要手动启动网络,不然没有enss33选项 需要启动 /mnt/hgfs/dft_shared/init_env/initaial_env.sh 文件 2.解决方案 2.1 修改/etc/rc.d/rc.local 文件 /etc/rc.d/rc.local 文件会在 Linux 系统各项服务都启动完毕之后再被运行。所以你想要…...

go并发设计模式runner模式

go并发设计模式runner模式 真正运行的程序不可能是单线程运行的,go语言中最值得骄傲的就是CSP模型了,可以说go语言是CSP模型的实现。 假设现在有一个程序需要实现,这个程序有以下要求: 程序可以在分配的时间内完成工作&#xff0…...

nn.RNN解析

以下是RNN的计算公式,t时刻的隐藏状态H(t)等于前一时刻隐藏状态H(t-1)乘以参数矩阵,再加t时刻的输入x(t)乘以参数矩阵,最后再通过激活函数,等到t时刻隐藏状态。 下图是输出input和初始化的隐藏状态,当参数batch_first True时候&…...

How to monitor Spring Boot apps with the AppDynamics Java Agent

本文介绍如何使用 AppDynamics Java 代理监视 Azure Spring Apps 中的 Spring Boot 应用程序。 使用 AppDynamics Java 代理可以: 监视应用程序使用环境变量配置 AppDynamics Java 代理 在 AppDynamics 仪表板中检查所有监视数据 How to monitor Spring Boot app…...

Linux学习笔记12 systemd的其他命令

前文已经介绍了systemd在系统初始化中起到的作用和服务的管理和配置。这里补充一下systemd的其他工具和系统进程的管理 前文 Linux学习笔记10 系统启动初始化,服务和进程管理(上)-CSDN博客 Linux学习笔记11 系统启动初始化,服务…...

NGO-CNN-BiGRU-Attention北方苍鹰算法优化卷积双向门控循环单元时间序列预测,含优化前后对比

NGO-CNN-BiGRU-Attention北方苍鹰算法优化卷积双向门控循环单元时间序列预测,含优化前后对比 目录 NGO-CNN-BiGRU-Attention北方苍鹰算法优化卷积双向门控循环单元时间序列预测,含优化前后对比预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介…...

【分布式】分布式缓存

一、什么是分布式缓存 分布式缓存是一种将缓存数据存储在多个节点上的缓存方案。它通过将数据分散存储在多个节点的内存中,以提高系统的读取性能、降低数据库压力和提高系统可扩展性。 二、分布式缓存的优点 优点明细提高性能:分布式缓存可以将数据缓…...

深度学习中的迁移学习:应用与实践

引言 在深度学习领域,迁移学习(Transfer Learning)是一个非常强大且日益流行的概念,它通过将从一个任务中学到的知识应用于另一个任务,能够显著加快模型训练速度并提高其泛化能力。迁移学习在许多实际应用中都得到了广…...

28.UE5实现对话系统

目录 1.对话结构的设计(重点) 2.NPC对话接口的实现 2.1创建类型为pawn的蓝图 2.2创建对话接口 3.对话组件的创建 4.对话的UI设计 4.1UI_对话内容 4.2UI_对话选项 4.3UI_对话选项框 5.对话组件的逻辑实现 通过组件蓝图,也就是下图中的…...

Redis中的分布式锁(步步为营)

分布式锁 概述 分布式锁指的是,所有服务中的所有线程都去获取同一把锁,但只有一个线程可以成功的获得锁,其他没有获得锁的线程必须全部等待,直到持有锁的线程释放锁。 分布式锁是可以跨越多个实例,多个进程的锁 分布…...

CentOS 7安装mysql+JDK+Tomcat完成流程

一.安装mysql 即使是新的linux服务器,也要先验证是否有mysql已经安装,如果有进行卸载原版本,一定要确认是否mysql已不再使用 原安装情况(直接执行命令即可) whereis mysql rpm -qa | grep -i mysql rpm -e perl-DBD-M…...

C++笔记之不同框架中事件循环的核心函数:io_run()、ros_spin()、app_exec()

C笔记之不同框架中事件循环的核心函数:io_run()、ros_spin()、app_exec() code review! 参考笔记 1.qt-C笔记之使用QtConcurrent异步地执行槽函数中的内容,使其不阻塞主界面 2.qt-C笔记之QThread使用 3.qt-C笔记之多线程架构模式:事件信号监…...

C++异常处理

目录 一、异常的概念 二、异常的使用 (1)异常的抛出和捕获 (2)异常的重新抛出 (3)异常安全 (4)异常规范 三、自定义异常体系 四、c标注异常体系 五、异常的优缺点 在之前我们…...

【数据结构】哈希 ---万字详解

unordered系列关联式容器 在C98中,STL提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到log_2 N,即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也不理想。最好 的查询是&#xff0c…...

4399大数据面试题及参考答案(数据分析和数据开发)

对数据分析的理解 数据分析是一个从数据中提取有价值信息以支持决策的过程。它涵盖了数据收集、清洗、转换、建模和可视化等多个环节。 首先,数据收集是基础。这包括从各种数据源获取数据,例如数据库、文件系统、网络接口等。这些数据源可以是结构化的数据,如关系型数据库中…...

快速理解倒排索引在ElasticSearch中的作用

一.基础概念 定义: 倒排索引是一种数据结构,用来加速文本数据的搜索和检索,和传统的索引方式不同,倒排索引会被每个词汇项与包含该词汇项的文档关联起来,从而去实现快速的全文检索。 举例: 在传统的全文…...

计算机视觉与3D重建:模型加速与质量优化的全栈实践

1. 项目概述:当计算机视觉遇见效率与精度革命最近,微软研究院在计算机视觉领域的两项进展引起了我的注意。一项是关于如何让模型“看”得更快更准,另一项则是关于如何让3D扫描模型从“毛坯”变成“精装”。这听起来像是两个独立的方向&#x…...

从阿里天池金融风控赛看实战:用XGBoost搞定贷款违约预测的完整流程与避坑指南

金融风控实战:XGBoost在贷款违约预测中的全流程解析 金融风控领域的机器学习应用正变得越来越普及,尤其是在贷款违约预测这一核心场景中。天池等数据竞赛平台为从业者提供了宝贵的实战演练机会,但如何将比赛经验转化为真实业务能力&#xff0…...

曲轴基于灵敏度的拓扑优化-CAE操作过程

前言 本示例展示了曲轴基于灵敏度的拓扑优化的基本工作流程。 该模型为简化曲轴模型,设计区域采用壳单元建模,轴体部分采用梁单元建模,壳单元与梁单元之间通过 RBE2 多点约束单元 进行耦合连接。 本次优化的目标是通过体积最小化实现曲轴的轻…...

VS Code图表神器:零配置用代码画UML、流程图与架构图

1. 项目概述:在VS Code里优雅地“画”图作为一名长期在技术文档、架构设计和日常笔记中与图表打交道的老兵,我深知一个痛点:从想法到一张清晰可用的图表,中间往往隔着“安装Java环境”、“配置GraphViz路径”、“折腾渲染引擎”等…...

IDEA 2023.2 版本中,如何一键开启Services面板管理你的Spring Boot微服务集群?

IDEA 2023.2 版本中如何高效管理Spring Boot微服务集群 微服务架构的流行让开发者面临一个现实挑战:如何在本地开发环境中高效管理多个同时运行的Spring Boot服务。传统方式需要逐个启动、切换终端查看日志,既浪费时间又容易造成混乱。JetBrains IDEA作为…...

德国工业4.0:从顶层设计到车间实践的制造业数字化转型

1. 工业4.0浪潮下的欧洲:一场由德国引领的深度变革提到德国制造,很多人脑海里蹦出来的词是“严谨”、“保守”甚至“刻板”。没错,德国人对于工业流程、制造工艺和质量标准的执着,有时近乎偏执。但正是这种对“传统”的极致坚守&a…...

搜搜果:一种面向AI生成内容验真与品牌可见度监测的实现方案

1. 问题定义 随着大语言模型(LLM)广泛集成到搜索、问答、推荐等场景中,出现两个可观测的问题: 内容可信性问题:模型会以高置信度输出事实上不存在的实体、事件或引用(幻觉,hallucination&#…...

【LeetCode 手撕算法】(二分查找)搜索插入位置、搜索二维矩阵、查找数组相同的所有位置、搜索旋转排序数组、旋转升序数组的最小值

复杂度为O(log n)且有序用二分查找35-搜索插入位置思路&#xff1a;二分查找&#xff0c;左右指针 求中间值注意&#xff1a;while的查询条件是>class Solution {public int searchInsert(int[] nums, int target) {int left0;int rightnums.length-1;while(left<right){…...

告别内存焦虑:用STM32+外部SRAM(IS62WV51216)实现大数组和GUI缓存

STM32外部SRAM实战&#xff1a;突破内存限制的工程化解决方案 当你在STM32上开发图形界面或处理音频流时&#xff0c;是否遇到过程序突然崩溃的窘境&#xff1f;那些隐藏在编译通过背后的内存溢出问题&#xff0c;往往在项目后期才暴露出来。最近接手的一个智能家居控制面板项目…...

Honey Select 2一站式智能优化方案:HS2-HF Patch高效整合200+插件

Honey Select 2一站式智能优化方案&#xff1a;HS2-HF Patch高效整合200插件 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch 还在为《Honey Select 2》的翻译不…...