弄了一整天,双token的思路总结,access_token,refresh_token
查了些资料,大概实现是拦截验证失败401,然后重放上次请求;
这是不太讲究的做法;原因:1、控制台401红色,不好看;2、业务逻辑千奇百怪,重放请求极大可能遇到各种问题。
目前实现方式如下:
1、请求发出前拦截
2、判断access_token是否过期
3、如果过期临时使用refresh_token访问,并异步更新access_token
下一次访问的时候,如果新的access_token已异步完成,使用新的access_token,没有完成还是用refresh_token访问;
稍有瑕疵是access_token异步未完成(授权时间未更新),refresh_token可能会多使用几次;(如果使用同步,感觉不如异步好)
extjs实现代码如下;
function asyncUpdateToken() {
return new Promise((resolve) => {
const { refresh_token } = localStore.getObject('user') || {};
fetch('/auth/refreshToken', {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
'authorization': `Bearer ${refresh_token}`,
},
}).then((response) => {
if (response.ok) {
resolve(response.text());
}
});
});
}
const checkTokenState = async function() {
const user = localStore.getObject('user') || {};
const { access_token } = user;
if (!access_token || tokenIsExp(access_token)) {
const newToken = await asyncUpdateToken();
const updatedUser = { ...user, access_token: newToken };
localStore.setObject('user', updatedUser);
if (newToken) {
const expTime = cmd.parseJwt(newToken)?.payload?.exp;
if (expTime) {
const expDate = new Date(expTime * 1000);
const formattedDate = Ext.Date.format(expDate, 'Y-m-d H:i:s');
console.log(`%c更新存储 ${formattedDate}`, 'color: #43bb88;font-size: 14px;font-weight: bold;');
}
}
}
};
const tokenIsExp = function(token) {
const { payload } = cmd.parseJwt(token);
return payload.exp * 1000 < Date.now(); // 已过期
};
function tokenExpToTime(token){
const { payload } = cmd.parseJwt(token);
let expDate = new Date(payload.exp * 1000);
return Ext.Date.format(expDate, 'Y-m-d H:i:s');
}
Ext.Ajax.addListener('beforerequest', function(conn, options, eOpts) {
if(1>2){
//这里无需token的请求跳过
return true
}
const { access_token, refresh_token } = localStore.getObject('user') || {};
console.log('START-----------------------------------')
console.log(`旧的存储 ${tokenExpToTime(access_token)} # ${tokenExpToTime(refresh_token)}`)
console.log(`当前时间 ${Ext.Date.format(new Date(), 'Y-m-d H:i:s')} @${tokenIsExp(access_token)
? '%c过期'
: '%c有效'}`,
`color: ${tokenIsExp(access_token)?"red":"green"} ;`)
void checkTokenState();
console.log(`xhr携带${options.url} exp${ tokenExpToTime(tokenIsExp(access_token) ? refresh_token : access_token) }`)
Ext.Ajax.setDefaultHeaders({
'authorization': `Bearer ${tokenIsExp(access_token) ? refresh_token : access_token}`
});
console.log('END-----------------------------------')
});
另外双token意义不是很大;
1、