首页 > 其他分享 >业务场景---Token无感刷新

业务场景---Token无感刷新

时间:2024-07-27 12:40:02浏览次数:11  
标签:refreshToken state token response --- Token return 无感

业务场景描述

假设用户正在填写一个复杂的表单,由于表单内容繁多,用户花费了很长时间才填完。这时,如果Token已经过期,系统会让用户重新登录,这种体验显然是非常糟糕的。为了避免这种情况,我们需要在Token即将过期或已经过期时,自动刷新Token,而不影响用户正在进行的操作。

技术实现思路

一、准备工作

  1. 前端框架选择:本文以Vue.js为例,结合Vue Router和Axios来实现Token无感刷新机制。
  2. 后端支持:后端需要提供刷新Token的接口,当接收到旧的Token时返回一个新的Token。

二、关键技术点

  1. 拦截请求:使用Axios拦截器来检测每一个请求的状态,如果发现Token过期,则触发刷新Token的逻辑。
  2. 刷新Token:实现一个专门用于刷新Token的方法,该方法会在旧的Token过期时自动调用并更新Token。
  3. 请求队列:在刷新Token期间,暂停其他需要Token的请求,待Token刷新成功后,重新发送这些请求。

三、具体实现步骤

1. 配置Axios拦截器

首先,配置Axios拦截器来检测请求和响应的状态,并在Token过期时触发刷新Token的逻辑。

import axios from 'axios';
import store from './store'; // 假设使用Vuex来管理全局状态
import router from './router';

let isRefreshing = false;
let requests = [];

axios.interceptors.request.use(
  config => {
    const token = store.state.token;
    if (token) {
      config.headers['Authorization'] = 'Bearer ' + token;
    }
    return config;
  },
  error => {
    return Promise.reject(error);
  }
);

axios.interceptors.response.use(
  response => {
    return response;
  },
  error => {
    const { config, response } = error;
    const originalRequest = config;
    
    if (response && response.status === 401) {
      if (!isRefreshing) {
        isRefreshing = true;
        return refreshToken().then(newToken => {
          store.commit('setToken', newToken);
          originalRequest.headers['Authorization'] = 'Bearer ' + newToken;
          processQueue(null, newToken);
          return axios(originalRequest);
        }).catch(err => {
          processQueue(err, null);
          store.commit('logout');
          router.push('/login');
          return Promise.reject(err);
        }).finally(() => {
          isRefreshing = false;
        });
      } else {
        return new Promise((resolve, reject) => {
          requests.push((token) => {
            originalRequest.headers['Authorization'] = 'Bearer ' + token;
            resolve(axios(originalRequest));
          });
        });
      }
    }
    return Promise.reject(error);
  }
);

function processQueue(error, token = null) {
  requests.forEach(promise => {
    if (error) {
      promise.reject(error);
    } else {
      promise.resolve(token);
    }
  });
  requests = [];
}

 

2. 实现刷新Token的方法

接下来,实现一个用于刷新Token的方法refreshToken。这个方法会调用后端接口来获取新的Token。

function refreshToken() {
  return new Promise((resolve, reject) => {
    axios.post('/auth/refresh', {
      refreshToken: store.state.refreshToken
    }).then(response => {
      if (response.data.success) {
        resolve(response.data.token);
      } else {
        reject(response.data.message);
      }
    }).catch(error => {
      reject(error);
    });
  });
}

 

3. 更新Vuex状态管理

确保在Vuex中有相关的状态和方法来管理Token和用户登录状态。

 

const store = new Vuex.Store({
  state: {
    token: localStorage.getItem('token') || '',
    refreshToken: localStorage.getItem('refreshToken') || '',
    user: {}
  },
  mutations: {
    setToken(state, token) {
      state.token = token;
      localStorage.setItem('token', token);
    },
    setRefreshToken(state, refreshToken) {
      state.refreshToken = refreshToken;
      localStorage.setItem('refreshToken', refreshToken);
    },
    logout(state) {
      state.token = '';
      state.refreshToken = '';
      state.user = {};
      localStorage.removeItem('token');
      localStorage.removeItem('refreshToken');
    }
  }
});

 

4. 处理登录逻辑

确保在用户登录时,正确地存储Token和刷新Token。

function login(credentials) {
  return axios.post('/auth/login', credentials).then(response => {
    store.commit('setToken', response.data.token);
    store.commit('setRefreshToken', response.data.refreshToken);
  });
}

 

总结:当用户在填写复杂表单时,即使Token过期也不会中断他们的操作,从而提供了更好的用户体验。这个机制不仅适用于表单填写,还可以广泛应用于任何需要长时间交互的Web应用场景中。

 

标签:refreshToken,state,token,response,---,Token,return,无感
From: https://www.cnblogs.com/zx618/p/18326822

相关文章

  • 04-Scala高级特性
    1.TraitobjectCH_0213_Trait{defmain(args:Array[String]):Unit={valintelligentCar=newIntelligentCar()intelligentCar.fly()intelligentCar.say()intelligentCar.drive()}}traitPerson{defsay():Unit={println(&qu......
  • 2024年第四届网络通信与信息安全国际学术会议(ICNCIS 2024,8月23-25)
    2024年第四届网络通信与信息安全国际学术会议(ICNCIS2024)将于2024年8月23-25日于杭州召开。会议围绕网络通信在信息安全领域中的最新研究成果,为来自国内外高等院校、科学研究所、企事业单位的专家、教授、学者、工程师等提供一个分享专业经验,扩大专业网络,面对面交流新思想......
  • Pythonanywhere - ping:套接字:不允许操作
    请帮忙。我有一个Telegram机器人,当我从Bash控制台启动他时,它每60秒ping一次静态IP-它工作正常,但每天停止工作一次。我尝试使用“始终开启任务”,但在日志文件中收到“ping:套接字:不允许操作”。我有5美元帐户,我能做什么?从Bash控制台运行时我看到的内容:---17......
  • 计算机组成与体系结构-CPU组成
    CPU由控制器和运算器两大部分组成,在控制器的控制之下,运算器存储器和输入输出设备等部件构成了一个整体。CPU的控制器程序计数器(PC):存放下一条指令在内存的地址指令寄存器(IR):存放即将要执行的指令指令译码器(ID):翻译指令(操作码+操作地址)地址寄存器(AR):保存当前CPU所......
  • 读书笔记-《从码农到工匠》+ 《程序员的底层思维》
    思想很重要。在晚上睡不着的时候就刷到了这本《程序员的底层思维》看了下目录。就下单了。作者是阿里巴巴的大佬。已经实现财富自由了吧。要学习的思维有哪些呢。第一就是抽象了。抽离+具象。抽象越高。挣的越多。哈哈。金字塔、分类、层次、分治、简单、成长(这个思维对人生......
  • MySQL索引详解full-text,b-tree,hash,r-tree
    一、MySQL索引类型mysql里目前只支持4种索引分别是:full-text,b-tree,hash,r-treeb-tree索引应该是mysql里最广泛的索引的了,除了archive基本所有的存储引擎都支持它.1.full-text索引full-text在mysql里仅有myisam支持它,而且支持full-text的字段只有char、varchar、text数据类型......
  • STM32+ESP8266-连接阿里云-创建云产品流转实现STM32与Android app通讯(1)
    前言本文章的内容为STM32通过ESP8266利用AT指令连接阿里云平台,并创建设备和创建云产品流转主题,来为实现Androidapp与STM32的发送接收数据做准备。Androidapp的实现由于篇幅不宜过长,将放到下一篇文章中。演示视频实现一个简单的app来控制stm32开关灯、蜂鸣器、门(舵机),显示温......
  • 【九大高校联合支持,学生易中,已确认ISSN号,见刊检索有保障!】2024年电力电子与电气工程国
    随着科技的不断进步和社会的发展,电气工程在各个领域都发挥着重要作用,它涉及到了电力系统、电子技术、自动控制等多个方面。近年来,人工智能、大数据、云计算等技术也不断更迭,使得电气工程也更加注重智能化、数字化的发展以及结合人工智能、机器学习的应用。时下,电气工程仍......
  • 计算机组成与体系结构-指令系统
    指令指令(又称机器指令):是指示计算机执行某种操作的命令,是计算机运行的最小功能单位由二进制表示,一条指令通常包括操作码字段和地址码字段两部分。操作码指出是什么操作,操作数直接指出操作数本身或者其对应地址。指令系统CISC(复杂指令系统):指令数量多,支持的寻址方式多,研制......
  • springboot机场投诉管理平台-计算机毕业设计源码22030
    摘要随着航空运输业的迅速发展,机场的客流量不断增加,旅客对机场服务的质量和效率也提出了更高的要求。为了提高机场的服务质量,及时处理旅客的投诉,建立一个高效、便捷的机场投诉管理平台显得尤为重要。本项目旨在设计与实现一个基于SpringBoot的机场投诉管理平台,以满足机场......