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

前端實現(xiàn)Token無感刷新的實戰(zhàn)指南+源碼

 更新時間:2025年12月12日 09:45:28   作者:Technical genius  
前端實現(xiàn)Token無感刷新主要通過雙Token機(jī)制(Access Token和Refresh Token)結(jié)合請求攔截器完成,本文將和大家詳細(xì)介紹一下具體的實現(xiàn)方法,感興趣的小伙伴可以了解下

介紹

前端實現(xiàn)Token無感刷新主要通過雙Token機(jī)制(Access Token和Refresh Token)結(jié)合請求攔截器完成。Access Token用于API訪問且生命周期較短(如1-2小時),Refresh Token用于刷新Access Token且生命周期較長(如7天)。

實現(xiàn)原理

在響應(yīng)攔截器中捕獲401狀態(tài)碼,觸發(fā)Refresh Token流程。刷新期間通過標(biāo)志位(如isRefreshing)防止重復(fù)請求,并將過期請求暫存隊列中,待獲取新Token后重新發(fā)送。

核心步驟

Token存儲‌:Access Token建議存內(nèi)存(如Vuex),Refresh Token需存HttpOnly Cookie提升安全性。

攔截器配置‌:

  • 請求攔截器自動添加有效Access Token;
  • 響應(yīng)攔截器對401狀態(tài)碼調(diào)用刷新接口,刷新失敗則跳轉(zhuǎn)登錄頁。

時間校驗‌:可結(jié)合登錄時間與當(dāng)前時間差,在特定區(qū)間(如1-2小時)內(nèi)觸發(fā)刷新。

代碼示例

以下為基于Axios的完整實現(xiàn):

1.TokenManager.js

class TokenManager {
  constructor() {
    this.isRefreshing = false;
    this.requestsQueue = [];
  }

  // 存儲Token
  setTokens(accessToken, refreshToken) {
    localStorage.setItem('accessToken', accessToken);
    localStorage.setItem('refreshToken', refreshToken);
  }

  getAccessToken() {
    return localStorage.getItem('accessToken');
  }

  getRefreshToken() {
    return localStorage.getItem('refreshToken');
  }

  removeTokens() {
    localStorage.removeItem('accessToken');
    localStorage.removeItem('refreshToken');
  }

  // 刷新Token核心邏輯
  async refreshToken() {
    if (this.isRefreshing) {
      return new Promise((resolve) => {
        this.requestsQueue.push(resolve);
      });
    }
    
    this.isRefreshing = true;
    try {
      const response = await axios.post('/api/auth/refresh', {
        refreshToken: this.getRefreshToken()
      });
      
      const newAccessToken = response.data.accessToken;
      localStorage.setItem('accessToken', newAccessToken);
      
      // 執(zhí)行隊列中的請求
      this.requestsQueue.forEach(callback => callback(newAccessToken));
      this.requestsQueue = [];
      return newAccessToken;
    } catch (error) {
      this.requestsQueue = [];
      this.removeTokens();
      window.location.href = '/login';
      throw error;
    } finally {
      this.isRefreshing = false;
    }
  }
}

export const tokenManager = new TokenManager();

2.axiosConfig.js

import axios from 'axios';
import { tokenManager } from './tokenManager.js';

// 創(chuàng)建axios實例
const service = axios.create({
  baseURL: process.env.VITE_API_BASE_URL,
  timeout: 10000
});

// 請求攔截器
service.interceptors.request.use(
  (config) => {
    const token = tokenManager.getAccessToken();
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// 響應(yīng)攔截器
service.interceptors.response.use(
  (response) => {
    return response;
  },
  async (error) => {
    const { config, response } = error;
    
    // 處理Token過期情況
    if (response?.status === 401 && !config._retry) {
      config._retry = true;
      
      try {
        const newToken = await tokenManager.refreshToken();
        config.headers.Authorization = `Bearer ${newToken}`;
        return service(config);
      } catch (refreshError) {
        return Promise.reject(refreshError);
      }
    }
    return Promise.reject(error);
  }
);

export default service;

3.LoginTimeManager.js

export class LoginTimeManager {
  static setLoginTime() {
    localStorage.setItem('loginTime', Date.now().toString());
  }

  static shouldRefreshToken() {
    const loginTime = localStorage.getItem('loginTime');
    if (!loginTime) return false;

    const currentTime = Date.now();
    const elapsed = currentTime - parseInt(loginTime);
    const oneHour = 60 * 60 * 1000;
    const twoHours = 2 * oneHour;

    return elapsed > oneHour && elapsed < twoHours;
  }
}

4.authDemo.vue

<template>
  <div class="auth-container">
    <h2>Token無感刷新演示</h2>
    <button @click="handleLogin" class="login-btn">模擬登錄</button>
    <button @click="fetchUserData" class="fetch-btn">獲取用戶數(shù)據(jù)</button>
    <div v-if="userData" class="data-display">
      <h3>用戶數(shù)據(jù):</h3>
      <pre>{{ JSON.stringify(userData, null, 2) }}</pre>
    </div>
  </div>
</template>

<script>
import axios from './axiosConfig.js';
import { tokenManager } from './tokenManager.js';
import { LoginTimeManager } from './loginHandler.js';

export default {
  name: 'AuthDemo',
  data() {
    return {
      userData: null
    };
  },
  methods: {
    async handleLogin() {
      try {
        const response = await axios.post('/api/auth/login', {
        username: 'user',
        password: 'pass'
        });
        
        const { accessToken, refreshToken } = response.data;
        tokenManager.setTokens(accessToken, refreshToken);
        LoginTimeManager.setLoginTime();
        alert('登錄成功!');
      } catch (error) {
        alert('登錄失?。?);
      }
    },
    
    async fetchUserData() {
      try {
        const response = await axios.get('/api/user/profile');
        this.userData = response.data;
      } catch (error) {
        console.error('獲取用戶數(shù)據(jù)失敗:', error);
      }
    }
  },
  mounted() {
    // 全局點擊監(jiān)聽觸發(fā)Token刷新
    document.addEventListener('click', async () => {
      if (LoginTimeManager.shouldRefreshToken() && !window.isRefreshing) {
        window.isRefreshing = true;
        try {
          await tokenManager.refreshToken();
          LoginTimeManager.setLoginTime();
        } finally {
          window.isRefreshing = false;
        }
      }
    });
  }
};
</script>

<style scoped>
.auth-container {
  padding: 20px;
  max-width: 800px;
  margin: 0 auto;
}

.login-btn, .fetch-btn {
  margin: 10px;
  padding: 10px 20px;
  background: #4CAF50;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}

.data-display {
  margin-top: 20px;
  padding: 15px;
  background: #f5f5f5;
  border-radius: 8px;
}
</style>

文件作用

TokenManager.js 的作用

TokenManager.js 負(fù)責(zé)Token的存儲管理和刷新邏輯核心實現(xiàn)。它通過雙Token機(jī)制(Access Token和Refresh Token)來確保認(rèn)證連續(xù)性,當(dāng)Access Token過期時自動使用Refresh Token獲取新的Access Token。該文件實現(xiàn)了防止重復(fù)刷新的標(biāo)志位控制(isRefreshing)和過期請求的隊列管理(requestsQueue),確保在刷新期間到達(dá)的請求能夠在新Token獲取后重新發(fā)送。同時提供完整的Token設(shè)置、獲取和清理方法,并在刷新失敗時自動跳轉(zhuǎn)登錄頁面。

axiosConfig.js 的作用

axiosConfig.js 專門配置Axios的請求和響應(yīng)攔截器。在請求攔截器中自動為每個API請求添加有效的Access Token到Authorization頭部。在響應(yīng)攔截器中捕獲401狀態(tài)碼(Token過期),并調(diào)用TokenManager的刷新方法。該文件還負(fù)責(zé)在Token刷新成功后,使用新Token重新發(fā)送之前失敗的請求,確保用戶操作不被中斷。

LoginTimeManager.js 的作用

LoginTimeManager.js 提供基于時間的Token刷新策略。它記錄用戶登錄時間,并通過計算當(dāng)前時間與登錄時間的時間差來判斷是否應(yīng)該主動刷新Token。這種時間校驗機(jī)制可以作為401狀態(tài)碼的補充,在Token即將過期但尚未過期時提前刷新,進(jìn)一步優(yōu)化用戶體驗。

authDemo.vue 的作用

authDemo.vue 是前端界面組件,負(fù)責(zé)用戶交互和功能演示。它提供登錄按鈕觸發(fā)認(rèn)證流程,并展示獲取用戶數(shù)據(jù)等受保護(hù)接口的調(diào)用效果。該組件還集成了全局點擊監(jiān)聽,在特定時間窗口內(nèi)觸發(fā)Token刷新,展示無感刷新的實際運行效果。

這四個文件共同協(xié)作:TokenManager處理核心刷新邏輯,axiosConfig攔截網(wǎng)絡(luò)請求,LoginTimeManager提供時間策略,authDemo則展示完整功能。這種模塊化設(shè)計使得代碼結(jié)構(gòu)清晰,易于維護(hù)和擴(kuò)展。

關(guān)鍵優(yōu)化點

  • 防抖刷新‌:通過標(biāo)志位控制刷新頻率,避免短時間多次刷新。
  • 錯誤處理‌:Refresh Token過期時清理本地存儲并跳轉(zhuǎn)登錄。
  • 時間安全‌:優(yōu)先依賴服務(wù)端401狀態(tài)碼而非本地時間判斷。

此方案在Token過期時自動靜默更新,用戶操作不受中斷,顯著提升體驗。

到此這篇關(guān)于前端實現(xiàn)Token無感刷新的實戰(zhàn)指南+源碼的文章就介紹到這了,更多相關(guān)前端無感刷新token內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

大港区| 昆山市| 车致| 静乐县| 苗栗县| 日照市| 大冶市| 郧西县| 城固县| 广宗县| 团风县| 永川市| 阿合奇县| 泸西县| 时尚| 小金县| 于田县| 彭山县| 咸阳市| 新巴尔虎右旗| 深州市| 乐昌市| 什邡市| 聂拉木县| 财经| 扎囊县| 彝良县| 华阴市| 织金县| 响水县| 龙海市| 巴塘县| 高州市| 平阴县| 南通市| 土默特左旗| 延长县| 垫江县| 江西省| 旺苍县| 甘南县|