You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular:双Token场景下HTTP请求前Token校验方案咨询

解决页面内API请求前的Token过期校验问题

这问题我之前在项目里也碰到过——路由守卫只能管页面跳转的场景,页面内的异步API请求确实覆盖不到。最靠谱的方案就是给你的HTTP客户端(比如Axios、Fetch)加请求拦截器,让它在每次发请求前自动完成Token校验和刷新逻辑,完美补全路由守卫的盲区。下面给你拆解具体实现步骤:

1. 先封装一个Token过期校验工具函数

首先需要一个通用函数来判断token_b是否过期,建议提前几秒判定过期(比如30秒),避免网络延迟导致请求到达后端时刚好过期:

function isTokenExpired(token) {
  if (!token) return true; // 没有Token直接判定为过期
  try {
    // 解析JWT的Payload部分(注意:仅前端校验,后端仍会做最终校验)
    const payload = JSON.parse(atob(token.split('.')[1]));
    const expireTime = payload.exp * 1000 - 30000; // 提前30秒过期
    return Date.now() > expireTime;
  } catch (err) {
    // 解析失败(比如Token格式错误)也判定为过期
    return true;
  }
}

2. 给HTTP客户端添加请求拦截器

以常用的Axios为例,通过拦截器在请求发出前统一处理Token逻辑,还能解决并发请求重复刷新Token的问题:

import axios from 'axios';

// 创建Axios实例
const apiClient = axios.create({ baseURL: '/your-api-base-url' });

// 刷新Token的Promise锁:避免多个并发请求同时触发刷新
let refreshTokenPromise = null;

// 请求拦截器
apiClient.interceptors.request.use(async (config) => {
  let tokenB = localStorage.getItem('token_b');
  const tokenA = localStorage.getItem('token_a');

  // 检查token_b是否过期
  if (isTokenExpired(tokenB)) {
    // 如果没有正在进行的刷新请求,发起刷新
    if (!refreshTokenPromise) {
      refreshTokenPromise = apiClient.post('/refresh-token', { token_a: tokenA })
        .then(res => {
          const newTokenB = res.data.token_b;
          localStorage.setItem('token_b', newTokenB);
          return newTokenB;
        })
        .catch(err => {
          // 刷新失败:说明token_a也失效了,跳转到登录页并清空Token
          localStorage.removeItem('token_a');
          localStorage.removeItem('token_b');
          window.location.href = '/login';
          return Promise.reject(err);
        })
        .finally(() => {
          // 刷新完成后释放锁
          refreshTokenPromise = null;
        });
    }

    // 等待刷新完成,获取新的token_b
    tokenB = await refreshTokenPromise;
  }

  // 将有效的token_b添加到请求头
  if (tokenB) {
    config.headers.Authorization = `Bearer ${tokenB}`;
  }

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

3. 如果用Fetch的替代方案

如果项目用原生Fetch,可以封装一个带Token校验的请求函数,所有API请求都通过这个函数发起:

async function fetchWithToken(url, options = {}) {
  let tokenB = localStorage.getItem('token_b');
  const tokenA = localStorage.getItem('token_a');

  if (isTokenExpired(tokenB)) {
    // 发起Token刷新请求
    const refreshRes = await fetch('/refresh-token', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ token_a: tokenA })
    });

    if (!refreshRes.ok) {
      // 刷新失败,跳登录页
      localStorage.removeItem('token_a');
      localStorage.removeItem('token_b');
      window.location.href = '/login';
      throw new Error('Token refresh failed');
    }

    const refreshData = await refreshRes.json();
    tokenB = refreshData.token_b;
    localStorage.setItem('token_b', tokenB);
  }

  // 给请求添加Token头
  options.headers = {
    ...options.headers,
    Authorization: `Bearer ${tokenB}`
  };

  return fetch(url, options);
}

方案优势

这种方式能覆盖所有HTTP请求场景:不管是页面内的异步API调用,还是路由跳转触发的请求,都会自动经过Token校验和刷新逻辑,和路由守卫形成互补,完全不需要在每个请求里手动写校验代码。

内容的提问来源于stack exchange,提问作者Kay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:08:11