最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

前端實(shí)現(xiàn)Token刷新機(jī)制的幾種方法

 更新時(shí)間:2025年08月24日 11:44:29   作者:Backstroke fish  
本文探討Token過期時(shí)的無痛刷新方案,包括定時(shí)器、請求攔截器、響應(yīng)攔截器,建議優(yōu)先采用后兩者以兼顧效率與場景適配性,感興趣的可以了解一下

背景

現(xiàn)在的網(wǎng)站基本會設(shè)置授權(quán)訪問,對于某些資源的訪問,需要有權(quán)限才能訪問或者操作,而服務(wù)端判斷用戶是否有權(quán)訪問或者操作,一般是通過Token實(shí)現(xiàn),而Token一般會設(shè)置過期時(shí)間,對于關(guān)于授權(quán)方面的技術(shù)這里不會具體描述,這篇主要針對的是用戶訪問授權(quán)資源的時(shí)候,Token過期了,如何實(shí)現(xiàn)無需再次登錄,無痛刷新Token,重新請求。以下是幾種可實(shí)現(xiàn)的方法

在前端實(shí)現(xiàn)刷新 token(access token)的方法有多種,每種方法都有其優(yōu)點(diǎn)和缺點(diǎn)。以下是幾種常見的方法及其評估:

1. 基于定時(shí)器的自動刷新

實(shí)現(xiàn)方式

使用 setTimeoutsetInterval 定時(shí)在 token 過期前一定時(shí)間內(nèi)自動發(fā)起刷新請求。

let refreshTokenTimeout;

const setRefreshTokenTimer = (expiresIn) => {
  // 設(shè)置定時(shí)器,在 token 過期前 5 分鐘刷新
  const refreshTime = expiresIn - 300000; // 5分鐘
  refreshTokenTimeout = setTimeout(refreshToken, refreshTime);
}

const refreshToken = async () => {
  try {
    const response = await fetch('/refresh-token');
    const data = await response.json();
    // 假設(shè)返回?cái)?shù)據(jù)包含新的 access token 和它的過期時(shí)間(expiresIn)
    localStorage.setItem('refreshToken', data.refreshToken);
    setRefreshTokenTimer(data.expiresIn);
  } catch (error) {
    console.error("Failed to refresh token", error);
    // 可以根據(jù)需要處理錯(cuò)誤,例如跳轉(zhuǎn)到登錄頁面
  }
}

// 初次設(shè)置定時(shí)器,這種需要后臺返回token的過期時(shí)間,或者用戶登錄的時(shí)候獲取token的時(shí)候同時(shí)存儲當(dāng)前的時(shí)間于localStorage
setRefreshTokenTimer(initialExpiresIn);

優(yōu)點(diǎn)

  • 簡單易實(shí)現(xiàn):邏輯簡單,易于理解和實(shí)現(xiàn)。
  • 自動化管理:無需用戶干預(yù),token 刷新完全自動化。

缺點(diǎn)

  • 不適用于后臺刷新:如果用戶離開頁面或?yàn)g覽器 tab 被掛起,定時(shí)器可能無法正常工作。
  • 資源消耗:可能會導(dǎo)致不必要的網(wǎng)絡(luò)請求,特別是在用戶不活躍時(shí)。

2. 基于請求攔截器的刷新

實(shí)現(xiàn)方式

在每個(gè) API 請求之前檢查 token 是否即將過期,如果即將過期,則首先刷新 token,然后再繼續(xù)發(fā)送請求。

// 使用 Axios 作為示例請求庫
import axios from 'axios';

const http= axios.create({
  baseURL: '/api',
  timeout: 10000,
});

http.interceptors.request.use(async (config) => {
  const token = localStorage.getItem('refreshToken');
  const expiryTime = localStorage.getItem('tokenExpiryTime');

  if (expiryTime && Date.now() >= expiryTime - 300000) { // 提前5分鐘刷新
    const newTokenData = await refreshToken();
    config.headers['Authorization'] = `Bearer ${newTokenData.refreshToken}`;
  } else {
    config.headers['Authorization'] = `Bearer ${token}`;
  }

  return config;
}, (error) => {
  return Promise.reject(error);
});

const refreshToken = async () => {
  try {
    const response = await apiClient.post('/refresh-token');
    const data = await response.data;
    localStorage.setItem('refreshToken', data.refreshToken);
    localStorage.setItem('tokenExpiryTime', Date.now() + data.expiresIn);
    return data;
  } catch (error) {
    console.error("Failed to refresh token", error);
    throw error;
  }
};

// 在需要時(shí)使用 apiClient 發(fā)出請求
http.get('/some-protected-endpoint').then(response => {
  console.log(response.data);
});

優(yōu)點(diǎn)

  • 高效:僅在需要時(shí)刷新 token,減少不必要的網(wǎng)絡(luò)請求。
  • 適用于后臺刷新:即使頁面在后臺運(yùn)行,也能確保 token 始終有效。

缺點(diǎn)

  • 復(fù)雜度增加:需要處理并發(fā)刷新請求的問題,同一時(shí)刻多個(gè)請求可能觸發(fā)多次刷新。
    比如,getApi1,getApi2同時(shí)并發(fā)請求,都會經(jīng)過Token過期判斷,都會發(fā)情token刷新請求,對于頁面并發(fā)請求,比如多文件上傳之類的并發(fā),如果并發(fā)6條數(shù)據(jù),則會請求6次token的刷新。

  • 額外延遲:首次請求可能因?yàn)?token 刷新而略有延遲。

3. 基于響應(yīng)攔截器的刷新(最常用)

實(shí)現(xiàn)方式

當(dāng) API 請求返回 401 Unauthorized 錯(cuò)誤時(shí),嘗試刷新 token 并重新發(fā)送原始請求。

import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
const http: AxiosInstance = axios.create({
  baseURL: '/baseapi', //Mock
  timeout: 10000,
});
const openTokenRefresh = false; // 是否開啟token刷新,如果開啟,就設(shè)置為true就好
const pendingRequests: ((token: string) => void)[] = []; // 保存所有請求的回調(diào),用于刷新token后重新請求
const onTokenRefreshed = (token: string):void => {
  // 刷新token后,重新請求,
  pendingRequests.forEach((callback) => {
    callback(token);
  });
  pendingRequests.length = 0;
};
const addPendingRequest = (callback: (token: string) => void) => {
  pendingRequests.push(callback);
};
//是否正在刷新token
let isRefreshing = false;

http.interceptors.response.use((response: AxiosResponse<any>) => response, async (error) => {
  if (error.response && error.response.status === 401 && openTokenRefresh) {
  	//獲取refreshToken 
 	const refreshToken = localStorage.getItem('refreshToken');
    if (!refreshToken) {
        //沒有refreshToken,跳轉(zhuǎn)登錄頁面
      window.location.href('/login')
      return Promise.reject('登錄失效,請重新登錄');
    }
    if (!isRefreshing) {
      try{
         isRefreshing = true;
         //請求更新token
      	 const data= await updataToken(refreshToken);
       	 localStorage.setItem('token', data.token);
       	 localStorage.setItem('refreshToken', data.refreshToken);
       	 onTokenRefreshed(data.token);
       }catch(err){
       	  window.location.href('/login')
       	  return Promise.reject(err)
       }
       finally{
      	  isRefreshing = false
       }
    }
	      //存儲當(dāng)前請求
      return new Promise<AxiosResponse<any>>((resolve) => {
        addPendingRequest((newToken: string) => {
          response.config.headers['Authorization'] ='Bearer'+ newToken;
          resolve(http(response.config));
        });
      });
  }

  return Promise.reject(error);
});

優(yōu)點(diǎn)

  • 高效:只有在必要時(shí)才刷新 token,避免不必要的請求。
  • 靈活性:能夠處理 token 失效后的各種情況,包括并發(fā)問題。

缺點(diǎn)

  • 復(fù)雜度較高:需要處理并發(fā)刷新、請求隊(duì)列等問題,代碼復(fù)雜度高。
  • 延遲:第一次請求失敗后需要等待 token 刷新,再次重試,可能會增加延遲。

總結(jié)

方法優(yōu)點(diǎn)缺點(diǎn)
基于定時(shí)器的自動刷新簡單易實(shí)現(xiàn),自動化管理不適用于后臺刷新,可能導(dǎo)致不必要的網(wǎng)絡(luò)請求
基于請求攔截器的刷新高效,適用于后臺刷新,減少不必要的網(wǎng)絡(luò)請求,復(fù)雜度增加,需要處理并發(fā)刷新問題,同一時(shí)刻多個(gè)請求可能觸發(fā)多次刷新。首次請求可能延遲
基于響應(yīng)攔截器的刷新只有在必要時(shí)才刷新 token,避免不必要的請求,能夠處理 token 失效后的各種情況,包括并發(fā)問題。首次請求失敗可能增加延遲

選擇哪種方法取決于你的具體需求和系統(tǒng)架構(gòu),通?;谡埱髷r截器和響應(yīng)攔截器的方法更為普遍,因?yàn)樗鼈兡軌蚋玫貞?yīng)對復(fù)雜的實(shí)際場景。

到此這篇關(guān)于前端實(shí)現(xiàn)Token刷新機(jī)制的幾種方法的文章就介紹到這了,更多相關(guān)前端實(shí)現(xiàn)Token刷新內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Layui 導(dǎo)航默認(rèn)展開和菜單欄選中高亮設(shè)置的方法

    Layui 導(dǎo)航默認(rèn)展開和菜單欄選中高亮設(shè)置的方法

    今天小編就為大家分享一篇Layui 導(dǎo)航默認(rèn)展開和菜單欄選中高亮設(shè)置的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-09-09
  • Sortable.js功能強(qiáng)大的JavaScript 拖拽庫示例詳解

    Sortable.js功能強(qiáng)大的JavaScript 拖拽庫示例詳解

    SortableJS 是一個(gè)強(qiáng)大、靈活且易于使用的 JavaScript 庫,適用于各種類型的拖放排序需求,這篇文章主要介紹了Sortable.js功能強(qiáng)大的JavaScript 拖拽庫示例詳解,需要的朋友可以參考下
    2025-01-01
  • JS 添加千分位與去掉千分位的示例

    JS 添加千分位與去掉千分位的示例

    本文為大家詳細(xì)介紹下使用JS添加千分位以及去掉千分位的實(shí)現(xiàn)代碼,感興趣的朋友可以參考下哈,希望對大家有所幫助
    2013-07-07
  • JavaScript實(shí)現(xiàn)批量重命名文件

    JavaScript實(shí)現(xiàn)批量重命名文件

    這篇文章主要為大家詳細(xì)介紹了如何利用JavaScript實(shí)現(xiàn)批量重命名文件,文中的示例代碼講解詳細(xì),有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-12-12
  • js兩行代碼按指定格式輸出日期時(shí)間

    js兩行代碼按指定格式輸出日期時(shí)間

    javascript兩行代碼即可實(shí)現(xiàn)按指定格式輸出日期時(shí)間,非常不錯(cuò),需要的朋友可以參考下
    2011-10-10
  • uniapp微信小程序?qū)崿F(xiàn)一個(gè)頁面多個(gè)倒計(jì)時(shí)

    uniapp微信小程序?qū)崿F(xiàn)一個(gè)頁面多個(gè)倒計(jì)時(shí)

    這篇文章主要為大家詳細(xì)介紹了uniapp微信小程序?qū)崿F(xiàn)一個(gè)頁面多個(gè)倒計(jì)時(shí),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • javascript簡單判斷輸入內(nèi)容是否合法的方法

    javascript簡單判斷輸入內(nèi)容是否合法的方法

    這篇文章主要介紹了javascript簡單判斷輸入內(nèi)容是否合法的方法,以驗(yàn)證用戶名是否為數(shù)字與字母組成為例,分析了javascript正則驗(yàn)證的思路與實(shí)現(xiàn)方法,需要的朋友可以參考下
    2016-05-05
  • 微信小程序?qū)崿F(xiàn)卡片層疊滑動

    微信小程序?qū)崿F(xiàn)卡片層疊滑動

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)卡片層疊滑動,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • uni-app動態(tài)修改主題色的方法詳解

    uni-app動態(tài)修改主題色的方法詳解

    最近在看uniapp開發(fā)app時(shí)需要實(shí)現(xiàn)動態(tài)修改主題色的功能,這篇文章主要給大家介紹了關(guān)于uni-app動態(tài)修改主題色的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12
  • 深入理解Javascript里的依賴注入

    深入理解Javascript里的依賴注入

    我喜歡引用這句話,“程序是對復(fù)雜性的管理”。計(jì)算機(jī)世界是一個(gè)巨大的抽象建筑群。我們簡單的包裝一些東西然后發(fā)布新工具,周而復(fù)始?,F(xiàn)在思考下,你所使用的語言包括的一些內(nèi)建的抽象函數(shù)或是低級操作符。這在JavaScript里是一樣的
    2014-03-03

最新評論

中超| 房产| 景宁| 东兴市| 辽中县| 固阳县| 涟水县| 江川县| 孝感市| 沭阳县| 长寿区| 福建省| 滦南县| 托克托县| 峡江县| 霍州市| 巴青县| 漠河县| 阿克| 定安县| 沂源县| 榆中县| 韶关市| 合山市| 铜陵市| 贵溪市| 金川县| 仙桃市| 塔城市| 巴东县| 社旗县| 札达县| 寿光市| 鄢陵县| 玉溪市| 龙里县| 治多县| 监利县| 拉孜县| 乐至县| 龙泉市|