亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

前端實現(xiàn)無感刷新的詳細方案

 更新時間:2025年03月28日 10:18:34   作者:北辰alk  
無感刷新(Silent Refresh)是指在用戶無感知的情況下,通過技術手段自動更新身份憑證(如Token),維持用戶登錄狀態(tài)的技術方案,本文給大家介紹了前端實現(xiàn)無感刷新的詳細方案,需要的朋友可以參考下

一、什么是無感刷新?

1.1 核心概念

無感刷新(Silent Refresh)是指在用戶無感知的情況下,通過技術手段自動更新身份憑證(如Token),維持用戶登錄狀態(tài)的技術方案。主要解決以下痛點:

  • 傳統(tǒng)Token過期強制退出影響用戶體驗
  • 減少重復登錄操作
  • 保持長期會話的有效性

1.2 典型應用場景

場景說明
JWT認證Access Token過期自動刷新
OAuth2.0使用Refresh Token獲取新憑證
敏感操作維持長時間操作不中斷

二、實現(xiàn)原理與方案對比

2.1 技術方案對比

方案優(yōu)點缺點適用場景
定時檢測實現(xiàn)簡單時間誤差大短期會話
請求攔截精確控制需要全局處理常規(guī)Web應用
Web Worker不阻塞主線程復雜度高大型應用
Service Worker離線可用需要HTTPSPWA應用

2.2 核心實現(xiàn)流程

三、基礎版實現(xiàn)(Axios攔截器方案)

3.1 創(chuàng)建Axios實例

// src/utils/request.js
import axios from 'axios'

const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 10000
})

3.2 添加請求攔截器

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

3.3 響應攔截器處理邏輯

// 響應攔截器
let isRefreshing = false
let requests = []

service.interceptors.response.use(
  (response) => {
    return response.data
  },
  async (error) => {
    const { config, response } = error
    
    // Token過期處理
    if (response.status === 401 && !config._retry) {
      
      // 存儲待重試請求
      if (!isRefreshing) {
        isRefreshing = true
        
        try {
          // 刷新Token
          const newToken = await refreshToken()
          
          // 存儲新Token
          localStorage.setItem('access_token', newToken)
          
          // 重試隊列
          requests.forEach(cb => cb(newToken))
          requests = []
          
          // 重試原請求
          config.headers.Authorization = `Bearer ${newToken}`
          return service(config)
        } catch (refreshError) {
          // 刷新失敗處理
          localStorage.clear()
          window.location.href = '/login'
          return Promise.reject(refreshError)
        } finally {
          isRefreshing = false
        }
      }
      
      // 將未完成的請求加入隊列
      return new Promise((resolve) => {
        requests.push((token) => {
          config.headers.Authorization = `Bearer ${token}`
          resolve(service(config))
        })
      })
    }
    
    return Promise.reject(error)
  }
)

3.4 Token刷新函數(shù)

async function refreshToken() {
  const refreshToken = localStorage.getItem('refresh_token')
  if (!refreshToken) {
    throw new Error('缺少刷新令牌')
  }
  
  try {
    const { data } = await axios.post('/api/auth/refresh', {
      refresh_token: refreshToken
    })
    
    return data.access_token
  } catch (error) {
    throw new Error('令牌刷新失敗')
  }
}

四、進階優(yōu)化方案

4.1 并發(fā)請求控制

class TokenRefreshManager {
  constructor() {
    this.subscribers = []
    this.isRefreshing = false
  }

  subscribe(callback) {
    this.subscribers.push(callback)
  }

  onRefreshed(token) {
    this.subscribers.forEach(callback => callback(token))
    this.subscribers = []
  }

  async refresh() {
    if (this.isRefreshing) {
      return new Promise(resolve => {
        this.subscribe(resolve)
      })
    }
    
    this.isRefreshing = true
    try {
      const newToken = await refreshToken()
      this.onRefreshed(newToken)
      return newToken
    } finally {
      this.isRefreshing = false
    }
  }
}

export const tokenManager = new TokenRefreshManager()

4.2 定時檢測策略

// Token有效期檢測
function setupTokenCheck() {
  const checkInterval = setInterval(() => {
    const token = localStorage.getItem('access_token')
    if (token && isTokenExpired(token)) {
      tokenManager.refresh().catch(() => {
        clearInterval(checkInterval)
      })
    }
  }, 60 * 1000) // 每分鐘檢查一次
}

// JWT解碼示例
function isTokenExpired(token) {
  const payload = JSON.parse(atob(token.split('.')[1]))
  const exp = payload.exp * 1000
  const now = Date.now()
  return now > exp - 5 * 60 * 1000 // 提前5分鐘刷新
}

4.3 Web Worker實現(xiàn)

// worker.js
self.addEventListener('message', async (e) => {
  if (e.data.type === 'refreshToken') {
    try {
      const response = await fetch('/api/refresh', {
        method: 'POST',
        body: JSON.stringify({
          refresh_token: e.data.refreshToken
        })
      })
      const data = await response.json()
      self.postMessage({ success: true, token: data.access_token })
    } catch (error) {
      self.postMessage({ success: false, error })
    }
  }
})

// 主線程調(diào)用
const worker = new Worker('./worker.js')

function refreshWithWorker() {
  return new Promise((resolve, reject) => {
    worker.postMessage({
      type: 'refreshToken',
      refreshToken: localStorage.getItem('refresh_token')
    })
    
    worker.onmessage = (e) => {
      if (e.data.success) {
        resolve(e.data.token)
      } else {
        reject(e.data.error)
      }
    }
  })
}

五、安全增強措施

5.1 安全存儲方案

// 安全存儲類
class SecureStorage {
  private encryptionKey: string
  
  constructor(key: string) {
    this.encryptionKey = key
  }

  setItem(key: string, value: string) {
    const encrypted = CryptoJS.AES.encrypt(value, this.encryptionKey)
    localStorage.setItem(key, encrypted.toString())
  }

  getItem(key: string) {
    const encrypted = localStorage.getItem(key)
    if (!encrypted) return null
    
    return CryptoJS.AES.decrypt(encrypted, this.encryptionKey)
      .toString(CryptoJS.enc.Utf8)
  }
}

// 初始化實例
const storage = new SecureStorage('your-secret-key')
storage.setItem('refresh_token', 'your-refresh-token')

5.2 雙Token校驗流程

5.3 防御措施

// 防止CSRF攻擊示例
function addCsrfProtection(config) {
  const csrfToken = getCsrfToken() // 從Cookie獲取
  if (csrfToken) {
    config.headers['X-CSRF-TOKEN'] = csrfToken
  }
  return config
}

// 速率限制
let refreshCount = 0
setInterval(() => {
  refreshCount = Math.max(0, refreshCount - 2)
}, 60 * 1000)

async function safeRefresh() {
  if (refreshCount > 5) {
    throw new Error('刷新過于頻繁')
  }
  refreshCount++
  return refreshToken()
}

六、多框架適配實現(xiàn)

6.1 Vue3 Composition API實現(xiàn)

<script setup>
import { ref } from 'vue'
import { useAxios } from '@vueuse/integrations/useAxios'

const { execute } = useAxios(
  '/api/data',
  { method: 'GET' },
  {
    immediate: false,
    onError: async (error) => {
      if (error.response?.status === 401) {
        await refreshToken()
        execute() // 自動重試
      }
    }
  }
)
</script>

6.2 React Hooks實現(xiàn)

import { useEffect } from 'react'
import axios from 'axios'

function useSilentRefresh() {
  useEffect(() => {
    const interceptor = axios.interceptors.response.use(
      response => response,
      async error => {
        if (error.response.status === 401) {
          await refreshToken()
          return axios.request(error.config)
        }
        return Promise.reject(error)
      }
    )
    
    return () => {
      axios.interceptors.response.eject(interceptor)
    }
  }, [])
}

6.3 Angular攔截器實現(xiàn)

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(private auth: AuthService) {}

  intercept(req: HttpRequest<any>, next: HttpHandler) {
    return next.handle(req).pipe(
      catchError(error => {
        if (error.status === 401) {
          return this.auth.refresh().pipe(
            switchMap(() => {
              const authReq = req.clone({
                setHeaders: { Authorization: `Bearer ${this.auth.token}` }
              })
              return next.handle(authReq)
            })
          )
        }
        return throwError(error)
      })
    )
  }
}

七、性能優(yōu)化方案

7.1 請求隊列管理

class RequestQueue {
  constructor() {
    this.queue = []
    this.isProcessing = false
  }

  add(request) {
    return new Promise((resolve, reject) => {
      this.queue.push({ request, resolve, reject })
      if (!this.isProcessing) this.process()
    })
  }

  async process() {
    this.isProcessing = true
    while (this.queue.length) {
      const { request, resolve, reject } = this.queue.shift()
      try {
        const response = await request()
        resolve(response)
      } catch (error) {
        reject(error)
      }
    }
    this.isProcessing = false
  }
}

7.2 內(nèi)存緩存優(yōu)化

const tokenCache = {
  accessToken: null,
  refreshToken: null,
  expiresAt: 0,

  get access() {
    if (Date.now() < this.expiresAt) {
      return this.accessToken
    }
    return null
  },

  async refresh() {
    const { access_token, expires_in } = await refreshToken()
    this.accessToken = access_token
    this.expiresAt = Date.now() + expires_in * 1000
    return access_token
  }
}

7.3 指數(shù)退避重試

async function retryWithBackoff(fn, retries = 3, delay = 1000) {
  try {
    return await fn()
  } catch (error) {
    if (retries <= 0) throw error
    await new Promise(resolve => setTimeout(resolve, delay))
    return retryWithBackoff(fn, retries - 1, delay * 2)
  }
}

八、生產(chǎn)環(huán)境注意事項

8.1 安全規(guī)范

  1. HTTPS必須啟用:防止中間人攻擊
  2. 設置合理有效期
    • Access Token:15-30分鐘
    • Refresh Token:7-30天 
  3. 權限分離:Refresh Token僅用于獲取新Access Token

8.2 監(jiān)控指標

指標監(jiān)控方式報警閾值
刷新成功率日志統(tǒng)計<95%
并發(fā)請求數(shù)性能監(jiān)控>100/秒
Token泄露次數(shù)安全掃描>0次

8.3 災備方案

  • 服務降級:刷新失敗時保留部分功能
  • 異地多活:認證中心多區(qū)域部署
  • 熔斷機制:異常時自動切換認證方式

九、完整實現(xiàn)流程圖

十、常見問題解答

Q1:如何防止Refresh Token被盜用?

  • 綁定設備指紋
  • 限制使用IP范圍
  • 設置單次有效性

Q2:移動端實現(xiàn)有何不同?

  • 使用安全存儲(Keychain/Keystore)
  • 結合生物認證
  • 考慮網(wǎng)絡切換場景

Q3:如何處理多標簽頁場景?

// 使用BroadcastChannel同步狀態(tài)
const channel = new BroadcastChannel('auth')

channel.addEventListener('message', (event) => {
  if (event.data.type === 'token_refreshed') {
    localStorage.setItem('access_token', event.data.token)
  }
})

function broadcastNewToken(token) {
  channel.postMessage({ type: 'token_refreshed', token })
}

十一、總結與展望

11.1 技術總結

  • 實現(xiàn)核心:請求攔截 + Token刷新隊列
  • 關鍵優(yōu)化:并發(fā)控制 + 安全存儲
  • 擴展方案:多框架適配 + 性能優(yōu)化

11.2 未來趨勢

  1. 無密碼認證:WebAuthn標準普及
  2. 零信任架構:持續(xù)身份驗證
  3. 區(qū)塊鏈身份:去中心化認證

以上就是前端實現(xiàn)無感刷新的詳細方案的詳細內(nèi)容,更多關于前端無感刷新的資料請關注腳本之家其它相關文章!

相關文章

  • 微信小程序如何獲取用戶頭像和昵稱

    微信小程序如何獲取用戶頭像和昵稱

    這篇文章主要介紹了微信小程序如何獲取用戶頭像和昵稱,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-09-09
  • JavaScript調(diào)試之console.log調(diào)試的一個小技巧分享

    JavaScript調(diào)試之console.log調(diào)試的一個小技巧分享

    日常開發(fā)中經(jīng)常會需要console來查看當前對象的值。當然用debugger會更全面的查看,但是總有只喜歡用console的,比如我。下面這篇文章主要給大家分享了關于JavaScript調(diào)試之console.log調(diào)試的一個小技巧,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-08-08
  • js如何獲取訪問IP、地區(qū)、當前操作瀏覽器

    js如何獲取訪問IP、地區(qū)、當前操作瀏覽器

    這篇文章主要介紹了js如何獲取訪問IP、地區(qū)、當前操作瀏覽器,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-07-07
  • 解決bootstrap中modal遇到Esc鍵無法關閉頁面

    解決bootstrap中modal遇到Esc鍵無法關閉頁面

    Bootstrap,來自 Twitter,是目前最受歡迎的前端框架。Bootstrap 是基于 HTML、CSS、JAVASCRIPT 的,它簡潔靈活,使得 Web 開發(fā)更加快捷。不過在使用的過程中,我們還是會遇到各種小問題,今天我們探討的就是個人在使用中遇到的一個小BUG的修復。
    2015-03-03
  • JS 事件冒泡 示例代碼

    JS 事件冒泡 示例代碼

    JS 事件冒泡 示例代碼,大家可以參考下。
    2009-07-07
  • canvas軌跡回放功能實現(xiàn)

    canvas軌跡回放功能實現(xiàn)

    這篇文章主要介紹了canvas軌跡回放功能實現(xiàn)過程以及相關的代碼整理,跟著小編一起學習下吧。
    2017-12-12
  • js中實現(xiàn)多態(tài)采用和繼承類似的方法

    js中實現(xiàn)多態(tài)采用和繼承類似的方法

    首先定義一個抽象類,其中調(diào)用一些虛方法,虛方法在抽象類中沒用定義,而是通過其具體的實現(xiàn)類來實現(xiàn)
    2014-08-08
  • JavaScript設計模式之單例模式詳解

    JavaScript設計模式之單例模式詳解

    單例模式(Singleton Pattern)是一種創(chuàng)建型設計模式,確保一個類只有一個實例,并提供全局訪問該實例的方式,這在某些場景下非常有用,例如配置管理類、日志類或數(shù)據(jù)庫連接管理類,需要的朋友可以參考下
    2024-08-08
  • thinkjs微信中控之微信鑒權登陸的實現(xiàn)代碼

    thinkjs微信中控之微信鑒權登陸的實現(xiàn)代碼

    這篇文章主要介紹了thinkjs微信中控之微信鑒權登陸的實現(xiàn)代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-08-08
  • 前端GET/POST請求下載文件多種方式代碼示例

    前端GET/POST請求下載文件多種方式代碼示例

    文件都是通過接口獲取的,前端通過調(diào)用接口將接口返回的文件下載,下面這篇文章主要給大家介紹了關于前端GET/POST請求下載文件的多種方式,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-06-06

最新評論