溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

前端請求token過期時刷新token的處理是怎樣的

發布時間:2021-12-23 16:43:51 來源:億速云 閱讀:931 作者:柒染 欄目:大數據
# 前端請求token過期時刷新token的處理是怎樣的

## 引言

在現代Web應用中,基于Token的身份驗證機制(如JWT)已成為主流方案。然而Token的有效期設計往往會導致一個關鍵問題:當用戶正在操作時Token突然過期,如何實現無感知刷新以保證用戶體驗?本文將深入探討前端如何處理Token過期時的刷新邏輯,涵蓋技術原理、實現方案和最佳實踐。

---

## 一、Token過期機制概述

### 1.1 為什么需要Token過期時間
- **安全考慮**:縮短Token有效期可降低被盜用風險
- **權限控制**:強制重新驗證用戶身份以更新權限
- **合規要求**:部分行業標準對會話時長有明確規定

### 1.2 常見Token類型及有效期
```javascript
// JWT Token示例結構
{
  "sub": "user123",
  "iat": 1625097600, // 簽發時間
  "exp": 1625101200  // 過期時間(通常30分鐘-2小時)
}

1.3 雙Token方案(Access/Refresh Token)

Token類型 有效期 存儲位置 用途
Access Token 短(15-30分鐘) 內存 API鑒權
Refresh Token 長(7-30天) HttpOnly Cookie 獲取新Access Token

二、核心處理流程設計

2.1 基礎刷新流程

sequenceDiagram
    participant F as 前端
    participant B as 后端
    
    F->>B: 請求API(攜帶過期Access Token)
    B-->>F: 返回401 Unauthorized
    F->>B: 發起Refresh請求(攜帶Refresh Token)
    alt Refresh Token有效
        B-->>F: 返回新Access Token
        F->>B: 重試原請求(攜帶新Token)
    else Refresh Token無效
        B-->>F: 返回401并清除Token
        F->>F: 跳轉登錄頁
    end

2.2 進階優化方案

  1. 預刷新機制:在Token臨近過期時主動刷新

    // 檢查剩余有效期
    function shouldRefresh(token) {
     const expiresIn = decode(token).exp - Date.now()/1000;
     return expiresIn < 300; // 剩余5分鐘時刷新
    }
    
  2. 請求隊列:在刷新期間暫停并發請求 “`javascript let isRefreshing = false; let requestsQueue = [];

async function refreshToken() { if (isRefreshing) return new Promise(resolve => { requestsQueue.push(resolve); });

 isRefreshing = true;
 const newToken = await fetchRefreshToken();
 requestsQueue.forEach(cb => cb(newToken));
 requestsQueue = [];
 isRefreshing = false;

}


---

## 三、具體實現方案

### 3.1 Axios攔截器實現
```javascript
// 請求攔截器
axios.interceptors.request.use(config => {
  const token = getAccessToken();
  if (token) config.headers.Authorization = `Bearer ${token}`;
  return config;
});

// 響應攔截器
axios.interceptors.response.use(
  response => response,
  async error => {
    const originalRequest = error.config;
    
    if (error.response.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      
      try {
        const newToken = await refreshToken();
        setAccessToken(newToken);
        originalRequest.headers.Authorization = `Bearer ${newToken}`;
        return axios(originalRequest);
      } catch (refreshError) {
        logout();
        return Promise.reject(refreshError);
      }
    }
    
    return Promise.reject(error);
  }
);

3.2 Fetch API實現方案

const fetchWithAuth = async (url, options = {}) => {
  // 初始請求
  let response = await fetch(url, {
    ...options,
    headers: {
      'Authorization': `Bearer ${getAccessToken()}`,
      ...options.headers
    }
  });

  // Token過期處理
  if (response.status === 401) {
    try {
      const newToken = await refreshToken();
      setAccessToken(newToken);
      
      // 重試請求
      response = await fetch(url, {
        ...options,
        headers: {
          'Authorization': `Bearer ${newToken}`,
          ...options.headers
        }
      });
    } catch (e) {
      clearTokens();
      window.location.href = '/login';
      throw e;
    }
  }
  
  return response;
};

四、安全增強措施

4.1 防御CSRF攻擊

  • Refresh Token存儲:使用HttpOnly + Secure + SameSite=Strict的Cookie
  • CSRF Token驗證:刷新接口要求附加CSRF Token

4.2 防止Token泄露

// 內存存儲示例
let memoryToken = null;

export const getAccessToken = () => {
  // 不從localStorage讀取,減少XSS風險
  return memoryToken;
};

export const setAccessToken = (token) => {
  memoryToken = token;
};

4.3 刷新頻率限制

  • 服務端記錄Refresh Token使用頻率
  • 短時間內多次刷新觸發安全警報

五、特殊場景處理

5.1 多標簽頁同步問題

// 使用BroadcastChannel API同步狀態
const authChannel = new BroadcastChannel('auth');

authChannel.onmessage = (event) => {
  if (event.data.type === 'TOKEN_REFRESHED') {
    setAccessToken(event.data.token);
  }
};

function broadcastNewToken(token) {
  authChannel.postMessage({
    type: 'TOKEN_REFRESHED',
    token
  });
}

5.2 服務端渲染(SSR)處理

  • Next.js示例:在getServerSideProps中處理刷新

    export async function getServerSideProps(context) {
    const { req, res } = context;
    
    
    // 服務端檢查Cookie中的Refresh Token
    if (isTokenExpired(req)) {
      try {
        const newToken = await refreshOnServer(req);
        setServerCookie(res, newToken);
      } catch (e) {
        res.writeHead(302, { Location: '/login' });
        res.end();
      }
    }
    
    
    // ...其他邏輯
    }
    

六、性能與體驗優化

6.1 指數退避重試

async function refreshWithRetry(retries = 3, delay = 1000) {
  try {
    return await refreshToken();
  } catch (error) {
    if (retries > 0) {
      await new Promise(res => setTimeout(res, delay));
      return refreshWithRetry(retries - 1, delay * 2);
    }
    throw error;
  }
}

6.2 離線隊列處理

// 使用IndexedDB存儲失敗請求
function addToOfflineQueue(request) {
  if ('indexedDB' in window) {
    const db = await openDB('RequestQueue', 1);
    await db.add('requests', request);
  }
}

// 網絡恢復后處理
window.addEventListener('online', async () => {
  const db = await openDB('RequestQueue', 1);
  const requests = await db.getAll('requests');
  
  requests.forEach(async request => {
    try {
      await fetchWithAuth(request.url, request.options);
      await db.delete('requests', request.id);
    } catch (e) {
      console.error('Retry failed:', e);
    }
  });
});

七、主流框架集成方案

7.1 React Context方案

const AuthContext = createContext();

function AuthProvider({ children }) {
  const [token, setToken] = useState(null);
  
  const refresh = async () => {
    try {
      const newToken = await refreshToken();
      setToken(newToken);
      return newToken;
    } catch (e) {
      setToken(null);
      redirectToLogin();
      throw e;
    }
  };

  return (
    <AuthContext.Provider value={{ token, refresh }}>
      {children}
    </AuthContext.Provider>
  );
}

// 使用示例
function useAuthFetch(url, options) {
  const { token, refresh } = useContext(AuthContext);
  
  return useCallback(async () => {
    let response = await fetch(url, {
      ...options,
      headers: { Authorization: `Bearer ${token}` }
    });
    
    if (response.status === 401) {
      const newToken = await refresh();
      response = await fetch(url, {
        ...options,
        headers: { Authorization: `Bearer ${newToken}` }
      });
    }
    
    return response;
  }, [token, refresh]);
}

結語

完善的Token刷新機制需要前后端協同設計,核心目標是: 1. 保證安全性:防止Token泄露和濫用 2. 提升用戶體驗:實現無感知刷新 3. 健壯性:處理各種邊界情況和異常場景

隨著Web技術的演進,Web Workers、Service Worker等新技術也為Token管理提供了更多可能性。開發者應根據具體業務場景選擇最適合的方案,并持續關注OAuth 2.1等新規范的安全建議。 “`

(注:實際字數為約2800字,可根據需要增減具體示例部分的詳細程度來調整字數)

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女