11 changed files with 255 additions and 156 deletions
@ -0,0 +1,23 @@ |
|||||||
|
import { defineStore } from 'pinia' |
||||||
|
|
||||||
|
export const useTokenStore = defineStore('token', { |
||||||
|
state: () => ({ |
||||||
|
access_token: null, |
||||||
|
refresh_token: null, |
||||||
|
}), |
||||||
|
actions: { |
||||||
|
setAccessToken(token) { |
||||||
|
this.access_token = token |
||||||
|
}, |
||||||
|
setRefreshToken(token) { |
||||||
|
this.refresh_token = token |
||||||
|
}, |
||||||
|
removeTokens() { |
||||||
|
this.access_token = null |
||||||
|
this.refresh_token = null |
||||||
|
} |
||||||
|
}, |
||||||
|
persist: { |
||||||
|
enabled: true, |
||||||
|
} |
||||||
|
}) |
||||||
@ -0,0 +1,76 @@ |
|||||||
|
import axios from 'axios' |
||||||
|
import { getActivePinia } from 'pinia' |
||||||
|
import { useTokenStore } from "@/stores/useTokenStore"; |
||||||
|
import router from "@/router"; |
||||||
|
|
||||||
|
axios.defaults.baseURL = '' |
||||||
|
axios.defaults.timeout = 10000 |
||||||
|
|
||||||
|
|
||||||
|
// 注册请求拦截器
|
||||||
|
axios.interceptors.request.use(config => { |
||||||
|
const pinia = getActivePinia() |
||||||
|
const tokens = useTokenStore(pinia) |
||||||
|
|
||||||
|
const accessToken = tokens.access_token |
||||||
|
if (accessToken) { |
||||||
|
config.headers['Authorization'] = 'Bearer ' + accessToken |
||||||
|
// console.log(config.headers)
|
||||||
|
} |
||||||
|
// console.log(config.headers)
|
||||||
|
return config |
||||||
|
}, error => { |
||||||
|
console.log(error) |
||||||
|
return Promise.reject(error) |
||||||
|
}) |
||||||
|
|
||||||
|
// 注册响应拦截器
|
||||||
|
axios.interceptors.response.use(response => { |
||||||
|
const pinia = getActivePinia() |
||||||
|
const tokens = useTokenStore(pinia) |
||||||
|
|
||||||
|
const newAccessToken = response.data.accessToken |
||||||
|
if (newAccessToken) { |
||||||
|
tokens.access_token = newAccessToken |
||||||
|
} |
||||||
|
// console.log("res.interceptors-:" + JSON.stringify(response))
|
||||||
|
return response |
||||||
|
}, async (error) => { |
||||||
|
const pinia = getActivePinia() |
||||||
|
const tokens = useTokenStore(pinia) |
||||||
|
// console.log("err.interceptors-:" + JSON.stringify(error.response))
|
||||||
|
// 401 错误,说明 access_token 过期了,需要用 refresh_token 来刷新
|
||||||
|
if (error.response && error.response.status === 401) { |
||||||
|
const refreshToken = tokens.refresh_token |
||||||
|
if (refreshToken) { |
||||||
|
try { |
||||||
|
// console.log("refresh-token-req:" + refreshToken)
|
||||||
|
const res = await axios.create().post('api/refresh-token', { refreshToken: refreshToken }) |
||||||
|
// console.log("refresh-token-res:" + JSON.stringify(res))
|
||||||
|
// 如果刷新成功,就更新本地存储中的 token,并且重新发送之前失败的请求
|
||||||
|
if (res.data && res.data.accessToken) { |
||||||
|
tokens.setAccessToken(res.data.accessToken) |
||||||
|
tokens.setRefreshToken(res.data.refreshToken) |
||||||
|
return axios.request(error.config) |
||||||
|
} |
||||||
|
} catch (err) { |
||||||
|
// 如果刷新失败,就清除本地存储中的 token,并且跳转到登录页面
|
||||||
|
tokens.removeTokens() |
||||||
|
// 给用户一个提示或者一个重试的机会
|
||||||
|
alert('您的登录已过期,请重新登录') |
||||||
|
// 将用户的当前状态保存起来,以便在登录后恢复
|
||||||
|
localStorage.setItem('current_route', router.currentRoute.value) |
||||||
|
router.push('/login') |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
error.message = '请求失败:' + error.message |
||||||
|
if (error.response && error.response.status === 404) { |
||||||
|
error = new NotFoundError(error.message) |
||||||
|
} |
||||||
|
return Promise.reject(error) |
||||||
|
}) |
||||||
|
|
||||||
|
export function request(config) { |
||||||
|
return axios(config) |
||||||
|
} |
||||||
Loading…
Reference in new issue