业务场景—Token无感刷新

业务场景描述

假设用户正在填写一个复杂的表单,由于表单内容繁多,用户花费了很长时间才填完。这时,如果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应用场景中。

 

发表评论

评论已关闭。

相关文章