token无感刷新 前端实现 一看就会!

场景:在往常的接口中我们通过从后端获取的token来进行身份识别,并且获取一些登录后的才能获取的一些数据,那么这个token有效期很短的时候,那么总不能让用户再登录一次来刷新token,所以我们需要提供一项操作,--------无感刷新(这个一般用在单点登录的时候)

首先呢用户第一次登录的时候,从后端获取两个token,一个是短期token 一个是长期token,用户之后获取一些权限性的数据时候是在请求头携带短期token的,这个长期token只有一个作用就是在短期token失效的时候来当作参数发给后端取更新短期token的。更新短期token的这个会单独设置一个接口。

下面是代码  无感刷新前端主要是逻辑代码,难度不大,下面的代码仅供参考

下面文件利用的tool.js的工具函数就是单纯从localStorage去获取值的操作,代码我就不贴了。

// axios请求拦截器页面

import { setToken, setRefreshToken, getToken } from './tools.js'
import { refreshToken, isRefreshRequest } from './api.js'



const ins = axios.create({
	baseURL: 'http://xxxxxxxxx',
	headers: {
		Authorization:
	}
});

ins.interceptors.response.use(async (res) => {
	if (res.headers.authorization) {
		const token = res.headers.authorization.replace('Bearor', '')
		setToken(token)
		ins.defaults.headers.Authorization = `Bearor${token}`
	}

	if (res.headers.refreshtoken) {
		const refreshtoken = res.headers.refreshtoken.replace('Bearor', '')
		setRefreshToken(refreshtoken)
	}
	if (res.data.code === 401 && !isRefreshRequest(res.config)) { //如果token失效并且不是更新token的接口时
		// 用长token去换短token
		const isSuccess = await refreshToken()
		if (isSuccess) { //获取新token成功的话
			// 有新的token后,重新请求
			console.log('重新请求');
			res.config.headers.Authorization = `Bearor${getToken()}` //重新请求前需要将更新后的新token更换掉之前无效的token,不然会死循环
			const resp = await ins.request(res.config)
			return resp
		} else {
			// 刷新失效,跳转登录页
			console.log('跳转到登录页');
		}
	}

	return res.data
})

export default ins;
//api文件页面

import request from './request'
import { getRefreshToken } from './tools.js'

export function login() {
	return request.post('/login')
}

export function reqProtected() {
	return request.post('/protected')
}

let promise;

export function refreshToken() {
	if (promise) { //这样操作是为了防止一种场景:在token失效的时候,同时调用了多个接口,这多个接口因为token失效 所以会执行多次更新token请求的操作。这个操作就是为了在同一时间点只会执行一次更新token
		return promise
	}

	promise = new Promise(async (resolve, reject) => {
		console.log('更新token');
		const resp = await request.get('/refreshToken', {
			headers: {
				Authorization: `Bearor${getRefreshToken()}`
			},
			__isRefreshToken: true, //添加一个自定义属性判断 用来识别该请求是刷新token用的
		})
		if (resp.code === 401) {
			resolve(false)
		} else {
			resolve(true)
		}

	})

	promise.finally(() => {
		promise = null
	})

}

//判断某个请求是否包含__isRefreshToken属性  进而判断是否是更新token的接口请求
export function isRefreshRequest(config) {
	return !!config.__isRefreshToken
}

猜你喜欢

转载自blog.csdn.net/m0_57033755/article/details/132637836