diff --git a/.eslintrc.js b/.eslintrc.js index b350399..fa5e68c 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -28,6 +28,7 @@ module.exports = { }, }, rules: { + 'import/no-cycle': 'off', 'prettier/prettier': ['error'], semi: 'error', radix: 'off', diff --git a/.husky/pre-commit b/.husky/pre-commit index cb63d6d..4c7b7a9 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,5 +1,4 @@ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" - # 限制git commit的命令 npx lint-staged diff --git a/src/api/auth.js b/src/api/auth.js index c29219a..b352023 100644 --- a/src/api/auth.js +++ b/src/api/auth.js @@ -9,3 +9,5 @@ export const getUserInfoByToken = (token) => token, }, }); +// 刷新token +export const refreshTokenData = (data) => service.put('/openapi/auth/token/refresh', data); diff --git a/src/api/interceptors.js b/src/api/interceptors.js index 1a5e76e..6173bd1 100644 --- a/src/api/interceptors.js +++ b/src/api/interceptors.js @@ -1,10 +1,14 @@ import { Message } from 'element-ui'; import router from '@/router'; +// eslint-disable-next-line import/no-cycle +import refreshTokenFun from '@/utils/refreshToken'; const ERROE_MSG = '请求异常,请重试'; const ERROR_MSG_400 = '请求参数异常'; -const ERROR_MSG_401 = '没有权限访问'; +const ERROR_MSG_401 = '没有权限访问或者登录过期'; +const ERROR_MSG_404 = '没有实际的值'; const ERROR_MSG_500 = '服务器异常'; +const whiteApi = ['/openapi/auth/token', '/openapi/auth/token/refresh']; const handleRespCode = (respData) => { switch (respData?.code) { case 400: @@ -13,6 +17,9 @@ const handleRespCode = (respData) => { case 401: Message.error(respData.msg || respData.message || ERROR_MSG_401); break; + case 404: + Message.error(respData.msg || respData.message || ERROR_MSG_404); + break; case 500: Message.error(respData.msg || respData.message || ERROR_MSG_500); break; @@ -20,10 +27,28 @@ const handleRespCode = (respData) => { break; } }; +const loginFun = () => { + setTimeout(() => { + router.push({ + name: 'Login', + }); + }, 600); +}; const setupInterceptors = (request) => { // 请求拦截器 request.interceptors.request.use( - (config) => config, + async (config) => { + // 白名单,不需要带token,不需要验证 + if (whiteApi.some((url) => config.url.includes(url))) { + return config; + } + const result = await refreshTokenFun(); + if (!result) { + loginFun(); + return config; + } + return config; + }, (error) => Promise.error(error || ERROE_MSG), ); @@ -34,9 +59,7 @@ const setupInterceptors = (request) => { const respData = resp.data; handleRespCode(respData); if (respData.code === 401) { - router.push({ - name: 'Login', - }); + loginFun(); } return Promise.resolve(respData); }, diff --git a/src/router/config/router.guards.js b/src/router/config/router.guards.js index d5ace20..e1fefd5 100644 --- a/src/router/config/router.guards.js +++ b/src/router/config/router.guards.js @@ -1,6 +1,7 @@ import NProgress from 'nprogress'; import 'nprogress/nprogress.css'; import authStorage from '@/utils/auth'; +import refreshTokenFun from '@/utils/refreshToken'; class RouterGuards { constructor(router) { @@ -16,8 +17,14 @@ class RouterGuards { } beforeEach() { - return this.router.beforeEach((to, from, next) => { - console.log('to', to); + return this.router.beforeEach(async (to, from, next) => { + const loginFun = () => { + setTimeout(() => { + this.router.push({ + name: 'Login', + }); + }, 600); + }; NProgress.start(); // 判断是否是白名单,白名单不需要进行登录验证 if (this.whiteRouter.includes(to.name)) { @@ -28,7 +35,13 @@ class RouterGuards { const { fullPath } = to; return next(`/login?redirecturl=${fullPath}`); } - next(); + // 判断是否需要刷新 + const result = await refreshTokenFun(); + if (result) { + next(); + } else { + loginFun(); + } } return true; }); diff --git a/src/utils/refreshToken.js b/src/utils/refreshToken.js new file mode 100644 index 0000000..55579d7 --- /dev/null +++ b/src/utils/refreshToken.js @@ -0,0 +1,31 @@ +import authStorage from '@/utils/auth'; +import { refreshTokenData } from '@/api/auth'; +import { Message } from 'element-ui'; + +const refreshTokenFun = async () => { + const tokenInfo = JSON.parse(authStorage.getTokenInfo() || 'null'); + // token不存在,直接重新登录 + if (!tokenInfo) { + return false; + } + // token存在,需要判断是否刷新 + // 1.判断是否超过刷新token的过期时间 + if (new Date().getTime() > tokenInfo.refreshTokenExpires || new Date().getTime() > tokenInfo.expires) { + Message.warning('登录过期,请重新登录'); + return false; + } + // 2.判断是否需要续约token,30分支到60分钟续约 + if (new Date().getTime() + 1000 * 60 * 30 >= tokenInfo.expires) { + const { token, refreshToken } = tokenInfo; + try { + const result = await refreshTokenData({ token, refreshToken }); + authStorage.setTokenInfo(result.data); + return true; + } catch (error) { + console.error(error); + return false; + } + } + return true; +}; +export default refreshTokenFun; diff --git a/src/views/Home/index.vue b/src/views/Home/index.vue index a94cbe6..92fb77f 100644 --- a/src/views/Home/index.vue +++ b/src/views/Home/index.vue @@ -1,3 +1,22 @@ + +