feat 自动刷新token

This commit is contained in:
damonyuan
2026-07-23 14:55:04 +08:00
parent 50ede7acfb
commit c072d43c87
6 changed files with 50 additions and 13 deletions

View File

@@ -1,7 +1,7 @@
import { Message } from 'element-ui';
import JSEncrypt from 'jsencrypt'
import config from '~/config/app'
import { createConsumeToken, clearConsumeToken } from '~/utils/consumeToken'
import { createConsumeToken, refreshConsumeToken } from '~/utils/consumeToken'
const passwordFields = [
'password', 'password2', 'password_confirm', 'passwordConfirm',
@@ -18,6 +18,7 @@ export default function ({ $axios, redirect, app, store }, inject) {
requestConfig.headers = requestConfig.headers || {}
requestConfig.headers.token = requestConfig.headers.token || store.state.token
if (
!requestConfig._consumeTokenRetry &&
requestConfig.data &&
passwordFields.some(field => typeof requestConfig.data[field] === 'string' && requestConfig.data[field])
) {
@@ -46,14 +47,22 @@ export default function ({ $axios, redirect, app, store }, inject) {
}
return requestConfig
})
$axios.onResponse((response) => {
$axios.onResponse(async (response) => {
const {
code,
show,
msg
} = response.data;
if (code == 0 && response.data.data && response.data.data.error === 'consume_token_invalid') {
clearConsumeToken()
const requestConfig = response.config || {}
const headers = requestConfig.headers || {}
const failedToken = headers['X-Consume-Token'] || ''
if (!requestConfig._consumeTokenRetry) {
requestConfig._consumeTokenRetry = true
await refreshConsumeToken(headers.token || store.state.token, failedToken)
return $axios.request(requestConfig)
}
return response
}
if (code == 0 && show && msg) {
Message({

View File

@@ -32,6 +32,11 @@ export async function createConsumeToken(loginToken) {
}
}
export async function refreshConsumeToken(loginToken, failedToken) {
clearConsumeToken(failedToken)
return createConsumeToken(loginToken)
}
async function issue(loginToken) {
const host = String(config.baseUrl || '').replace(/\/$/, '')
if (!host && typeof process !== 'undefined' && process.server) {
@@ -57,10 +62,14 @@ async function issue(loginToken) {
return token
}
export function clearConsumeToken() {
export function clearConsumeToken(expectedToken) {
if (expectedToken && cachedToken !== expectedToken) {
return false
}
cachedToken = ''
cachedLoginToken = ''
refreshAt = 0
return true
}
function clearCache() {

View File

@@ -101,9 +101,9 @@ class Login
{
return json([
'code' => 0,
'msg' => '消费Token无效或已过期',
'msg' => '',
'data' => ['error' => 'consume_token_invalid'],
'show' => 1,
'show' => 0,
'time' => 0,
]);
}

View File

@@ -90,7 +90,8 @@
var response = {
data: res.data,
statusCode: res.statusCode,
header: res.header
header: res.header,
config: config
};
if (!validateStatus || validateStatus(res.statusCode)) {
@@ -409,7 +410,7 @@
var config = Object.create(null); // 创建空对象,作为最终的合并结果
// 1.常规属性,如果用户配置了就用用户配置的,如果用户没配置,则用默认配置的;
var defaultToUserConfig = ["baseURL", "transformRequest", "transformResponse", "paramsSerializer", "timeout", "withCredentials", "adapter", "responseType", "xsrfCookieName", "xsrfHeaderName", "onUploadProgress", "onDownloadProgress", "maxContentLength", "validateStatus", "maxRedirects", "httpAgent", "httpsAgent", "cancelToken", "socketPath"];
var defaultToUserConfig = ["baseURL", "transformRequest", "transformResponse", "paramsSerializer", "timeout", "withCredentials", "adapter", "responseType", "xsrfCookieName", "xsrfHeaderName", "onUploadProgress", "onDownloadProgress", "maxContentLength", "validateStatus", "maxRedirects", "httpAgent", "httpsAgent", "cancelToken", "socketPath", "_consumeTokenRetry"];
defaultToUserConfig.forEach(function (prop) {
userConfig = userConfig || {}; // 如果用户配置里有

View File

@@ -33,6 +33,11 @@ export async function createConsumeToken(loginToken) {
}
}
export async function refreshConsumeToken(loginToken, failedToken) {
clearConsumeToken(failedToken)
return createConsumeToken(loginToken)
}
function issue(loginToken) {
return new Promise((resolve, reject) => {
const host = String(baseURL || '').replace(/\/$/, '')
@@ -68,10 +73,14 @@ function issue(loginToken) {
})
}
export function clearConsumeToken() {
export function clearConsumeToken(expectedToken) {
if (expectedToken && cachedToken !== expectedToken) {
return false
}
cachedToken = ''
cachedLoginToken = ''
refreshAt = 0
return true
}
function clearCache() {

View File

@@ -1,4 +1,4 @@
import axios from '../js_sdk/xtshadow-axios/axios.min'
import axios from '../js_sdk/xtshadow-axios/axios'
import JSEncrypt from 'jsencrypt'
import store from '../store'
import { paramsToStr, currentPage, tabbarList, acountList } from './tools'
@@ -6,7 +6,7 @@ import Cache from './cache'
import { TOKEN, BACK_URL } from '../config/cachekey'
import { baseURL } from '../config/app'
import { getWxCode, toLogin, wxMnpLogin } from './login'
import { createConsumeToken, clearConsumeToken } from './consumeToken'
import { createConsumeToken, refreshConsumeToken } from './consumeToken'
const passwordFields = [
'password', 'password2', 'password_confirm', 'passwordConfirm',
@@ -41,6 +41,7 @@ service.interceptors.request.use(
config.data = checkParams(config.data)
config.params = checkParams(config.params)
if (
!config._consumeTokenRetry &&
config.data &&
passwordFields.some((field) => typeof config.data[field] === 'string' && config.data[field])
) {
@@ -64,7 +65,7 @@ service.interceptors.request.use(
data.password_key_id = response.data.key_id || response.data.keyId
config.data = data
}
if (config.method == 'GET') {
if (config.method == 'GET' && !config._consumeTokenRetry) {
config.url += paramsToStr(config.params)
}
config.header = config.header || {}
@@ -88,7 +89,15 @@ service.interceptors.response.use(
const { code, show, msg, data } = response.data
const { route, options } = currentPage()
if (code == 0 && data && data.error === 'consume_token_invalid') {
clearConsumeToken()
const config = response.config || {}
const header = config.header || {}
const failedToken = header['X-Consume-Token'] || ''
if (!config._consumeTokenRetry) {
config._consumeTokenRetry = true
await refreshConsumeToken(header.token || Cache.get(TOKEN), failedToken)
return service(config)
}
return Promise.resolve(response.data)
}
if (code == 0 && show && msg) {
uni.showToast({