当前位置: 首页 > 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中的作用

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

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

大数据零基础学习day1之环境准备和大数据初步理解

学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 &#xff08;1&#xff09;设置网关 打开VMware虚拟机&#xff0c;点击编辑…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...

通过MicroSip配置自己的freeswitch服务器进行调试记录

之前用docker安装的freeswitch的&#xff0c;启动是正常的&#xff0c; 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...

comfyui 工作流中 图生视频 如何增加视频的长度到5秒

comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗&#xff1f; 在ComfyUI中实现图生视频并延长到5秒&#xff0c;需要结合多个扩展和技巧。以下是完整解决方案&#xff1a; 核心工作流配置&#xff08;24fps下5秒120帧&#xff09; #mermaid-svg-yP…...