思路:
- token的作用是一个请求标识,部分接口需要请求头添加token作为身份认证字段;
- 后端设定的token有效期是2个小时,过期后接口报错(401),需要更新token才能重新获取数据;
解决思路: 在请求拦截器中判断token是否超时,超时则自动重新获取token
代码
$http.beforeRequest = function(options) {
uni.showLoading({
title: '数据加载中...',
});
// 超时更新token
debouncedGetToken()
}
//使用第三方库
import jsrsasign from 'jsrsasign'
// 解析token
export const decodeToken = (token) => {
let obj = null
if (token !== '') {
const payload = jsrsasign.KJUR.jws.JWS.parse(token)
if (payload.hasOwnProperty('payloadObj')) {
obj = payload.payloadObj
}
}
return obj
}
// 每个页面都有很多接口,防止一下子重复调用多次
export function debounce(fn, delay = 100) {
let timer
return function() {
const that = this
const _args = arguments // 存一下传入的参数
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(function() {
fn.apply(that, _args)
}, delay)
}
}
export async function getToken() {
// 获取code
const res = await uni.login().catch(err => err)
if (res.errMsg !== 'login:ok') {
return uni.$showMsg('获取code失败!')
}
// 获取token;'/api/User/Login'-换成自己的接口, params-调用接口需要的参数
const {
data: loginResult
} = await uni.$http.post('/api/User/Login', params)
if (loginResult.code !== 200) return uni.$showMsg('更新失败!')
return loginResult.data.token
}
export let debouncedGetToken = debounce(async function() {
// 当前时间
const timestamp = Date.parse(new Date()) / 1000;
// uni.getStorageSync('exp')-第一次登录时存储的‘过期时间’
if (timestamp > uni.getStorageSync('exp')) {
try {
const token = await getToken({});
// vuex中更新token字符串
store.commit('m_user/updateToken', token);
// 解析token,获取新token的过期时间进行本地存储
const decodedToken = decodeToken(token);
uni.setStorageSync("exp", decodedToken.exp);
} catch (error) {
console.error("获取token失败", error);
}
}
}, 2000); // 设置防抖间隔为2000毫秒(2秒)
补充:(npm下载)
1.接口请求使用的封装网络请求,具体使用:@escook/request-miniprogram - npm (npmjs.com)
2.jsrsasign的使用参考:2022-uni-app解析token标准的方式-使用jsrsasign-爬坑过了_uniapp jsrsasign-CSDN博客