0

0

Service Worker中的认证令牌管理:实现请求等待与周期性刷新

碧海醫心

碧海醫心

发布时间:2025-10-03 10:57:01

|

711人浏览过

|

来源于php中文网

原创

service worker中的认证令牌管理:实现请求等待与周期性刷新

本文探讨了在Service Worker中高效管理周期性更新的认证令牌的策略。核心思想是利用Promise的不可变性,通过替换存储Promise的变量而非修改Promise本身,来确保网络请求在令牌刷新期间能等待并获取最新令牌。教程将详细介绍如何实现请求同步、错误处理及初始令牌获取,从而优化Service Worker的认证流程。

在现代Web应用中,Service Worker常被用于拦截和处理网络请求,从而实现离线能力、缓存管理和性能优化。当应用采用基于令牌的认证机制时,如何在Service Worker内部高效地管理这些认证令牌,特别是当令牌需要周期性刷新,并且在刷新期间所有新的网络请求都必须等待新令牌可用时,就成为了一个关键问题。

许多开发者可能会尝试寻找一种“可更新的Promise”或类似观察者模式的复杂机制来解决此问题。然而,Promise一旦被解析(fulfilled或rejected),其状态和值就不可更改。试图直接修改一个已存在的Promise是徒劳的。正确的策略是利用Promise的这种不可变性,通过巧妙地管理存储Promise的引用来达到目的。

核心策略:利用Promise引用替换实现请求同步

问题的核心在于,所有需要认证的请求都应该依赖于当前最新且有效的令牌。当令牌正在刷新时,后续请求应暂停并等待刷新完成;当刷新完成后,它们应使用新令牌继续。

解决方案的关键在于:

奇布塔
奇布塔

基于AI生成技术的一站式有声绘本创作平台

下载
  1. 维护一个变量,例如 currentAuthTokenPromise,它始终指向一个代表“获取当前有效令牌”的Promise。
  2. 当需要刷新令牌时(例如,通过定时器触发),创建一个新的Promise来执行令牌获取操作,并将 currentAuthTokenPromise 更新为指向这个新创建的Promise。
  3. 所有需要令牌的网络请求都简单地 await currentAuthTokenPromise。

这样,无论 currentAuthTokenPromise 是一个已经解析的Promise(令牌已可用),还是一个仍在进行中的Promise(令牌正在刷新),await 关键字都会确保请求在令牌可用之前暂停执行。当 currentAuthTokenPromise 被新的Promise替换后,所有后续的 await 操作都将等待新的Promise。

实现细节与示例代码

为了实现这一机制,我们需要一个函数来负责获取新令牌,一个变量来存储当前的令牌Promise,以及一个定时器来触发周期性刷新。同时,为了增强健壮性,我们还需要考虑错误处理和初始令牌的获取。

// 模拟获取新认证令牌的函数
// 实际应用中,这会是一个发起网络请求到认证服务器的异步操作
async function fetchNewAuthToken() {
  console.log("Service Worker: 正在获取新的认证令牌...");
  return new Promise((resolve, reject) => {
    // 模拟网络延迟和令牌生成
    setTimeout(() => {
      const success = Math.random() > 0.1; // 模拟90%成功率
      if (success) {
        const newToken = `Bearer_SW_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`;
        console.log("Service Worker: 新令牌获取成功:", newToken);
        resolve(newToken);
      } else {
        console.error("Service Worker: 令牌获取失败!");
        reject(new Error("Failed to fetch auth token"));
      }
    }, 1500); // 模拟1.5秒的网络请求
  });
}

// 用于存储当前令牌Promise的变量,初始为null
let currentAuthTokenPromise = null;

/**
 * 获取或刷新认证令牌。
 * 如果当前没有有效的令牌Promise,则发起获取新令牌的请求。
 * 如果令牌获取失败,则重置 currentAuthTokenPromise 为 null,以便下次重试。
 * @returns {Promise} 包含认证令牌的Promise
 */
async function getOrRefreshAuthToken() {
  if (currentAuthTokenPromise === null) {
    console.log("Service Worker: 令牌Promise为空,发起首次或重试获取。");
    currentAuthTokenPromise = fetchNewAuthToken().catch(error => {
      console.error("Service Worker: 令牌获取流程中捕获到错误:", error);
      currentAuthTokenPromise = null; // 获取失败,重置以便下次请求重试
      throw error; // 重新抛出错误,让调用者感知
    });
  }
  return currentAuthTokenPromise;
}

// Service Worker启动时立即获取令牌
getOrRefreshAuthToken();

// 设置定时器,每隔15分钟刷新令牌
// 注意:在实际Service Worker中,定时器可能因SW休眠而中断,
// 更好的做法是结合 'sync' 事件或在每次请求时检查令牌有效期。
const TOKEN_REFRESH_INTERVAL_MS = 15 * 60 * 1000; // 15分钟
setInterval(() => {
  console.log("Service Worker: 达到刷新间隔,准备刷新令牌。");
  currentAuthTokenPromise = null; // 清空当前Promise,强制下次调用 getOrRefreshAuthToken 时重新获取
  getOrRefreshAuthToken();
}, TOKEN_REFRESH_INTERVAL_MS);


// 拦截所有网络请求的 fetch 事件
self.addEventListener('fetch', event => {
  const { request } = event;
  // 假设只有特定路径的请求需要认证
  if (request.url.includes('/api/') && !request.url.includes('/api/auth')) { // 避免认证请求本身也需要令牌
    event.respondWith(
      (async () => {
        try {
          const token = await getOrRefreshAuthToken(); // 等待获取最新令牌
          const headers = new Headers(request.headers);
          headers.set('Authorization', token); // 添加认证头

          const authRequest = new Request(request, { headers });
          console.log(`Service Worker: 使用令牌 '${token.substring(0, 20)}...' 发起请求到 ${request.url}`);
          return fetch(authRequest); // 发起带有认证头的新请求
        } catch (error) {
          console.error(`Service Worker: 处理请求 ${request.url} 时令牌获取失败:`, error);
          // 可以返回一个错误响应,或者重定向到登录页
          return new Response(JSON.stringify({ error: 'Authentication required or failed' }), {
            status: 401,
            headers: { 'Content-Type': 'application/json' }
          });
        }
      })()
    );
  }
});

重要注意事项

  1. 错误处理与重试机制: 如示例代码所示,getOrRefreshAuthToken 函数内部包含了错误处理逻辑。如果 fetchNewAuthToken 失败,它会捕获错误并将 currentAuthTokenPromise 重置为 null。这意味着下一次有请求需要令牌时,会再次尝试获取新令牌,从而避免了因一次失败导致所有后续请求

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

236

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

438

2024.03.01

promise的用法
promise的用法

“promise” 是一种用于处理异步操作的编程概念,它可以用来表示一个异步操作的最终结果。Promise 对象有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。Promise的用法主要包括构造函数、实例方法(then、catch、finally)和状态转换。

306

2023.10.12

html文本框类型介绍
html文本框类型介绍

html文本框类型有单行文本框、密码文本框、数字文本框、日期文本框、时间文本框、文件上传文本框、多行文本框等等。详细介绍:1、单行文本框是最常见的文本框类型,用于接受单行文本输入,用户可以在文本框中输入任意文本,例如用户名、密码、电子邮件地址等;2、密码文本框用于接受密码输入,用户在输入密码时,文本框中的内容会被隐藏,以保护用户的隐私;3、数字文本框等等。

405

2023.10.12

PHP 高并发与性能优化
PHP 高并发与性能优化

本专题聚焦 PHP 在高并发场景下的性能优化与系统调优,内容涵盖 Nginx 与 PHP-FPM 优化、Opcode 缓存、Redis/Memcached 应用、异步任务队列、数据库优化、代码性能分析与瓶颈排查。通过实战案例(如高并发接口优化、缓存系统设计、秒杀活动实现),帮助学习者掌握 构建高性能PHP后端系统的核心能力。

101

2025.10.16

PHP 数据库操作与性能优化
PHP 数据库操作与性能优化

本专题聚焦于PHP在数据库开发中的核心应用,详细讲解PDO与MySQLi的使用方法、预处理语句、事务控制与安全防注入策略。同时深入分析SQL查询优化、索引设计、慢查询排查等性能提升手段。通过实战案例帮助开发者构建高效、安全、可扩展的PHP数据库应用系统。

86

2025.11.13

JavaScript 性能优化与前端调优
JavaScript 性能优化与前端调优

本专题系统讲解 JavaScript 性能优化的核心技术,涵盖页面加载优化、异步编程、内存管理、事件代理、代码分割、懒加载、浏览器缓存机制等。通过多个实际项目示例,帮助开发者掌握 如何通过前端调优提升网站性能,减少加载时间,提高用户体验与页面响应速度。

29

2025.12.30

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

10

2026.01.27

拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

109

2026.01.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.5万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号