关于token过期问题

本文介绍了服务器生成的Token的有效期设计以及如何通过refresh_token解决过期问题。重点讲述了在axios请求拦截器中添加token刷新逻辑,确保用户登录状态的持续性,同时处理401响应码并进行相应的刷新操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

登录成功之后后端会返回两个 Token:

  • token:访问令牌,有效期2小时

  • refresh_token:刷新令牌,有效期14天,用于访问令牌过期之后重新获取新的访问令牌

我们的项目接口中设定的 Token 有效期是 2 小时,超过有效期服务端会返回 401 表示 Token 无效或过期了。

为什么过期时间这么短?

  • 为了安全,例如 Token 被别人盗用

过期了怎么办?

  • 让用户重新登录,用户体验太差了

  • 使用 refresh_token 解决 token 过期

如何使用 refresh_token 解决 token 过期?

到课程的后面我们开发的业务功能丰富起来之后,再给大家讲解 Token 过期处理。

大家需要注意的是在学习测试的时候如果收到 401 响应码,请重新登录再测试

概述:服务器生成token的过程中,会有两个时间,一个是token失效时间,一个是token刷新时间,刷新时间肯定比失效时间长,当用户的 token 过期时,你可以拿着过期的token去换取新的token,来保持用户的登陆状态,当然你这个过期token的过期时间必须在刷新时间之内,如果超出了刷新时间,那么返回的依旧是 401。

处理流程:

  1. 在axios的拦截器中加入token刷新逻辑

  2. 当用户token过期时,去向服务器请求新的 token

  3. 把旧的token替换为新的token

  4. 然后继续用户当前的请求

在请求的响应拦截器中统一处理 token 过期:

/**
 * 封装 axios 请求模块
 */
import axios from "axios";
import jsonBig from "json-bigint";
import store from "@/store";
import router from "@/router";
// axios.create 方法:复制一个 axios
const request = axios.create({
  baseURL: "" // 基础路径
});
/**
 * 配置处理后端返回数据中超出 js 安全整数范围问题
 */
request.defaults.transformResponse = [
  function(data) {
    try {
      return jsonBig.parse(data);
    } catch (err) {
      return {};
    }
  }
];
// 请求拦截器
request.interceptors.request.use(
  function(config) {
    const user = store.state.user;
    if (user) {
      config.headers.Authorization = `Bearer ${user.token}`;
    }
    // Do something before request is sent
    return config;
  },
  function(error) {
    // Do something with request error
    return Promise.reject(error);
  }
);
// 响应拦截器
request.interceptors.response.use(
  // 响应成功进入第1个函数
  // 该函数的参数是响应对象
  function(response) {
    // Any status code that lie within the range of 2xx cause this function to trigger
    // Do something with response data
    return response;
  },
  // 响应失败进入第2个函数,该函数的参数是错误对象
  async function(error) {
    // Any status codes that falls outside the range of 2xx cause this function to trigger
    // Do something with response error
    // 如果响应码是 401 ,则请求获取新的 token
    // 响应拦截器中的 error 就是那个响应的错误对象
    console.dir(error);
    if (error.response && error.response.status === 401) {
      // 校验是否有 refresh_token
      const user = store.state.user;
      if (!user || !user.refresh_token) {
        router.push("/login");

        // 代码不要往后执行了
        return;
      }
      // 如果有refresh_token,则请求获取新的 token
      try {
        const res = await axios({
          method: "PUT",
          url: "",
          headers: {
            Authorization: `Bearer ${user.refresh_token}`
          }
        });
        // 如果获取成功,则把新的 token 更新到容器中
        console.log("刷新 token  成功", res);
        store.commit("setUser", {
          token: res.data.data.token, // 最新获取的可用 token
          refresh_token: user.refresh_token // 还是原来的 refresh_token
        });
        // 把之前失败的用户请求继续发出去
        // config 是一个对象,其中包含本次失败请求相关的那些配置信息,例如 url、method 都有
        // return 把 request 的请求结果继续返回给发请求的具体位置
        return request(error.config);
      } catch (err) {
        // 如果获取失败,直接跳转 登录页
        console.log("请求刷线 token 失败", err);
        router.push("/login");
      }
    }
    return Promise.reject(error);
  }
);
export default request;

<think>好的,我现在需要解决用户关于如何处理或刷新过期Token认证机制的问题。根据用户提供的三个引用内容,我需要先理解每个引用的重点,然后结合这些信息来构建一个清晰的解决方案。 首先,引用[1]提到在Vue后台中,当Token过期时,可以通过刷新请求来获取新的Token,然后使用新Token重新发起之前的请求。这里的关键点是使用一个订阅队列(refreshSubscribers)来暂存需要重新发起的请求,待新Token获取后再执行它们。这似乎是一种常见的处理方式,可以避免并发请求时多次刷新Token问题。 引用[2]指出,如果Refresh Token过期或被篡改,服务器会要求用户重新登录。这说明在设计中需要考虑Refresh Token的有效期和安全性,以及如何处理Refresh Token失效的情况,比如跳转到登录页面或提示用户重新认证。 引用[3]则提到两种用户场景:活跃用户应无感知刷新Token,而不活跃用户需要重新登录。这要求系统能够区分用户活跃状态,并设计相应的刷新策略,例如在每次请求时检查Token的有效期,快过期时自动刷新,或者在检测到Token过期后尝试用Refresh Token获取新Token。 接下来,我需要整合这些信息,形成一个分步骤的解决方案。首先,用户发起请求时,如果Token过期,应拦截请求,尝试用Refresh Token获取新Token。如果成功,则更新Token并重发原请求;如果失败,则跳转登录。同时,需要处理多个并发请求的情况,避免重复刷新Token。此外,还要考虑用户活跃状态下的自动刷新机制,例如定时刷新或根据Token有效期提前刷新。 可能需要注意的细节包括:如何存储和管理Token和Refresh Token,如何安全地发送刷新请求,如何处理异步操作和队列中的请求,以及错误处理逻辑,比如网络问题或服务器返回异常时的应对措施。此外,前端可能需要配合后端实现特定的刷新接口,并确保Refresh Token的安全存储,比如使用HttpOnly的Cookie来减少XSS攻击的风险。 然后,根据这些思考,我需要组织回答的结构,分步骤说明处理流程,并引用提供的参考资料来支持每个步骤。同时,生成相关问题需要考虑用户可能进一步想知道的内容,比如如何具体实现拦截请求、如何处理并发、如何设置Token有效期等。 最后,确保回答符合系统指令:使用正确的中文,数学公式用$...$,独立公式用$$...$$,虽然这个问题可能不涉及数学公式,但需要检查是否有其他格式要求。同时,生成的相关问题要自然且有针对性,帮助用户深入理解Token刷新的机制。</think>### 处理或刷新过期Token的认证机制步骤 #### 1. **Token过期检测与拦截请求** - 在每次发起API请求前,前端通过拦截器检查当前Token是否过期(例如通过解析JWT中的`exp`字段或后端返回的`401`状态码)[^3]。 - **实现示例**: ```javascript // 在axios拦截器中检查Token过期 axios.interceptors.request.use(config => { const token = localStorage.getItem('access_token'); if (token && isTokenExpired(token)) { return refreshTokenAndRetry(config); // 触发刷新Token逻辑 } return config; }); ``` #### 2. **使用Refresh Token获取新Token** - 若检测到Token过期前端向认证服务器发送包含`Refresh Token`的请求(例如`/auth/refresh`接口),获取新的`Access Token`和`Refresh Token`[^1]。 - **安全要求**: - Refresh Token应通过安全通道(如HTTPS)传输。 - Refresh Token建议存储在`HttpOnly Cookie`中,避免XSS攻击[^2]。 #### 3. **处理并发请求与订阅队列** - 为避免多个请求同时触发刷新Token,需将后续请求加入**订阅队列**,待新Token获取后重新发起。 - **实现示例**: ```javascript let isRefreshing = false; let refreshSubscribers = []; function refreshTokenAndRetry(config) { if (!isRefreshing) { isRefreshing = true; return axios.post('/auth/refresh', { refresh_token }) .then(response => { localStorage.setItem('access_token', response.data.access_token); refreshSubscribers.forEach(cb => cb()); refreshSubscribers = []; return axios(config); // 重新发起原始请求 }) .finally(() => isRefreshing = false); } else { return new Promise(resolve => { refreshSubscribers.push(() => resolve(axios(config))); }); } } ``` #### 4. **自动刷新与用户状态管理** - **活跃用户**:通过定时器或每次请求时检查Token剩余有效期,若临近过期(如剩余5分钟),自动刷新Token[^3]。 - **不活跃用户**:若Token和Refresh Token过期,跳转至登录页面并要求重新认证。 #### 5. **异常处理与降级策略** - **Refresh Token失效**:清除本地Token并跳转登录页。 - **网络错误**:重试刷新机制(如最多重试3次),超出后提示用户检查网络。 --- ### 相关问题 1. **如何安全地存储Refresh Token?** (涉及Cookie的`HttpOnly`、`Secure`属性与前端存储风险) 2. **如何设计Token的有效期与刷新时间?** (平衡安全性与用户体验,如Access Token设为15分钟,Refresh Token设为7天) 3. **如何处理多个标签页同时触发Token刷新的问题?** (通过全局状态或BroadcastChannel同步刷新状态) --- ### 引用说明 [^1]: 通过订阅队列管理并发请求,确保Token刷新后重试所有挂起请求。 : Refresh Token失效时需强制用户重新登录,保障系统安全。 [^3]: 根据用户活跃状态动态调整刷新策略,平衡无感体验与安全性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值