开发学习笔记

kkfile学习笔记

1.epub是运用epub.js来执行预览,后端只需要将数据以blob的形式传给前端,前端加载epub.js,页面就渲染出epub的内容。

2.xlsx文件是通过JODConverter依赖类来执行转换的,它可以把office文件转换为pdf、html等文件。jobconverter文档详解_jodconverter-优快云博客 ,先转换为html文件,再将其以流的形式输出到前端,并在其中添加了excel.header.js文件,然后可以显示编辑的功能了。

芋道源码的uniapp在token过期循环刷新的问题

芋道源码的uniapp中,用户第一次登录以后,系统会生成并返回两个token,一个是accessToken。accesstoken的过期时间是半个小时。另一个是resfreshToken,refreshToken的过期时间是12小时。在后续的请求中拦截器会自动把accesstoken加载到请求头上,后台接收到请求以后首先判断token是否存在且没有过期,如果过期,就返回401,前台接到401以后,就会发起refreshToken的请求,将refreshToken传入,后台接收到这个请求以后,判断refreshToken是否存在且没有过期,如验证不通过,返回的code!=1,前端就弹出重新登录的窗口;如果验证通过,就重新生成新的accesstoken,返回给前端;按理说,前端应该将这个新的token存储到本地,但正是因为之前的代码中没有对token进行存储,导致本地还是以前的token,然后系统请求的时候还是用的已过期的token,所以再次访问失败,陷入不断请求失败和刷新token的死循环中。解决的方案就是在refreshToken以后,把获取到的新的token存储到本地,这样就下次的请求就不会报401,代码如下:


/**
 * @description 响应拦截器
 */
http.interceptors.response.use(
	(response) => {
		// 约定:如果是 /auth/ 下的 URL 地址,并且返回了 accessToken 说明是登录相关的接口,则自动设置登陆令牌
		// if (response.config.url.indexOf('/member/auth/') >= 0 && response.data?.data?.accessToken) {
		// 	$store('user').setToken(response.data.data.accessToken, response.data.data.refreshToken);
		// }

		// 自定处理【loading 加载中】:如果需要显示 loading,则关闭 loading
		response.config.custom.showLoading && closeLoading();

		// 自定义处理【error 错误提示】:如果需要显示错误提示,则显示错误提示
		if (response.data.code !== 0) {
			// 特殊:如果 401 错误码,则跳转到登录页 or 刷新令牌
			if (response.data.code === 401) {
				return refreshToken(response.config);
			}

			// 错误提示
			if (response.config.custom.showError) {
				uni.showToast({
					title: response.data.msg || '服务器开小差啦,请稍后再试~',
					icon: 'none',
					mask: true,
				});
			}
		}
// 其他代码
}

let requestList = [] // 请求队列
let isRefreshToken = false // 是否正在刷新中
const refreshToken = async (config) => {

	// 如果当前已经是 refresh-token 的 URL 地址,并且还是 401 错误,说明是刷新令牌失败了,直接返回 Promise.reject(error)
	if (config.url.indexOf('/member/auth/refresh-token') >= 0) {
		return Promise.reject('error')
	}

	// 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了
	if (!isRefreshToken) {
		isRefreshToken = true
		// 1. 如果获取不到刷新令牌,则只能执行登出操作
		const refreshToken = getRefreshToken()
		if (!refreshToken) {
			return handleAuthorized()
		}
		// 2. 进行刷新访问令牌
		try {
			const refreshTokenResult = await AuthUtil.refreshToken(refreshToken);
			if (refreshTokenResult.code !== 0) {
				// 如果刷新不成功,直接抛出 e 触发 2.2 的逻辑
				// noinspection ExceptionCaughtLocallyJS
				throw new Error('刷新令牌失败');
			}
			//!!!!!!!不加这个代码的话,后续的请求还是在用原来的token,然后就还是报token失效,
			uni.setStorageSync('token', refreshTokenResult.data.accessToken);
			// 2.1 刷新成功,则回放队列的请求 + 当前请求
			config.header.Authorization = 'Bearer ' + getAccessToken()
			requestList.forEach((cb) => {
				cb()
			})
			requestList = []
			return request(config)
		} catch (e) {
			// 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。
			// 2.2 刷新失败,只回放队列的请求
			requestList.forEach((cb) => {
				cb()
			})
			// 提示是否要登出。即不回放当前请求!不然会形成递归
			return handleAuthorized()
		} finally {
			requestList = []
			isRefreshToken = false
		}
	} else {
		// 添加到队列,等待刷新获取到新的令牌
		return new Promise((resolve) => {
			requestList.push(() => {
				config.header.Authorization = 'Bearer ' +
					getAccessToken() // 让每个请求携带自定义token 请根据实际情况自行修改
				resolve(request(config))
			})
		})
	}
}

备注:后端代码在生成token以后,数据库和redis都会存一份,在后续查询的时候,是查的redis

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值