业务场景描述
假设用户正在填写一个复杂的表单,由于表单内容繁多,用户花费了很长时间才填完。这时,如果Token已经过期,系统会让用户重新登录,这种体验显然是非常糟糕的。为了避免这种情况,我们需要在Token即将过期或已经过期时,自动刷新Token,而不影响用户正在进行的操作。
技术实现思路
一、准备工作
- 前端框架选择:本文以Vue.js为例,结合Vue Router和Axios来实现Token无感刷新机制。
- 后端支持:后端需要提供刷新Token的接口,当接收到旧的Token时返回一个新的Token。
二、关键技术点
- 拦截请求:使用Axios拦截器来检测每一个请求的状态,如果发现Token过期,则触发刷新Token的逻辑。
- 刷新Token:实现一个专门用于刷新Token的方法,该方法会在旧的Token过期时自动调用并更新Token。
- 请求队列:在刷新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