前端请求token过期时刷新token的处理是怎样的

发布时间:2021-12-23 16:43:51 作者:柒染
来源:亿速云 阅读:905
# 前端请求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攻击

4.2 防止Token泄露

// 内存存储示例
let memoryToken = null;

export const getAccessToken = () => {
  // 不从localStorage读取,减少XSS风险
  return memoryToken;
};

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

4.3 刷新频率限制


五、特殊场景处理

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)处理


六、性能与体验优化

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字,可根据需要增减具体示例部分的详细程度来调整字数)

推荐阅读:
  1. vue的token刷新处理的方法
  2. Vue中拦截器对token过期处理的示例分析

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

token

上一篇:如何实现LinkedList源码解析

下一篇:mysql中出现1053错误怎么办

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》