Commit 7926ea989652d82399f62223a5f40476f657539f
1 parent
c738b2c8
修复 refresh token 过期时,不会自动跳转到首页的问题
Showing
1 changed file
with
79 additions
and
72 deletions
yudao-ui-admin/src/utils/request.js
| 1 | 1 | import axios from 'axios' |
| 2 | -import { Notification, MessageBox, Message } from 'element-ui' | |
| 2 | +import {Message, MessageBox, Notification} from 'element-ui' | |
| 3 | 3 | import store from '@/store' |
| 4 | 4 | import {getAccessToken, getRefreshToken, setToken} from '@/utils/auth' |
| 5 | 5 | import errorCode from '@/utils/errorCode' |
| ... | ... | @@ -7,6 +7,12 @@ import Cookies from "js-cookie"; |
| 7 | 7 | import {getPath, getTenantEnable} from "@/utils/ruoyi"; |
| 8 | 8 | import {refreshToken} from "@/api/login"; |
| 9 | 9 | |
| 10 | +// 需要忽略的提示。忽略后,自动 Promise.reject('error') | |
| 11 | +const ignoreMsgs = [ | |
| 12 | + "无效的刷新令牌", // 刷新令牌被删除时,不用提示 | |
| 13 | + "刷新令牌已过期" // 使用刷新令牌,刷新获取新的访问令牌时,结果因为过期失败,此时需要忽略。否则,会导致继续 401,无法跳转到登出界面 | |
| 14 | +] | |
| 15 | + | |
| 10 | 16 | // 是否显示重新登录 |
| 11 | 17 | export let isRelogin = { show: false }; |
| 12 | 18 | // Axios 无感知刷新令牌,参考 https://www.dashingdog.cn/article/11 与 https://segmentfault.com/a/1190000020210980 实现 |
| ... | ... | @@ -15,6 +21,7 @@ let requestList = [] |
| 15 | 21 | // 是否正在刷新中 |
| 16 | 22 | let isRefreshToken = false |
| 17 | 23 | |
| 24 | + | |
| 18 | 25 | axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8' |
| 19 | 26 | // 创建axios实例 |
| 20 | 27 | const service = axios.create({ |
| ... | ... | @@ -66,85 +73,85 @@ service.interceptors.request.use(config => { |
| 66 | 73 | }) |
| 67 | 74 | |
| 68 | 75 | // 响应拦截器 |
| 69 | -service.interceptors.response.use( async res => { | |
| 70 | - // 未设置状态码则默认成功状态 | |
| 71 | - const code = res.data.code || 200; | |
| 72 | - // 获取错误信息 | |
| 73 | - const msg = errorCode[code] || res.data.msg || errorCode['default'] | |
| 74 | - if (code === 401) { | |
| 75 | - // 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了 | |
| 76 | - if (!isRefreshToken) { | |
| 77 | - isRefreshToken = true; | |
| 78 | - // 1. 如果获取不到刷新令牌,则只能执行登出操作 | |
| 79 | - if (!getRefreshToken()) { | |
| 80 | - return handleAuthorized(); | |
| 81 | - } | |
| 82 | - // 2. 进行刷新访问令牌 | |
| 83 | - try { | |
| 84 | - const refreshTokenRes = await refreshToken() | |
| 85 | - // 2.1 刷新成功,则回放队列的请求 + 当前请求 | |
| 86 | - setToken(refreshTokenRes.data) | |
| 87 | - requestList.forEach(cb => cb()) | |
| 88 | - return service(res.config) | |
| 89 | - } catch (e) {// 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。 | |
| 90 | - // 2.2 刷新失败,只回放队列的请求 | |
| 91 | - requestList.forEach(cb => cb()) | |
| 92 | - // 提示是否要登出。即不回放当前请求!不然会形成递归 | |
| 93 | - return handleAuthorized(); | |
| 94 | - } finally { | |
| 95 | - requestList = [] | |
| 96 | - isRefreshToken = false | |
| 97 | - } | |
| 98 | - } else { | |
| 99 | - // 添加到队列,等待刷新获取到新的令牌 | |
| 100 | - return new Promise(resolve => { | |
| 101 | - requestList.push(() => { | |
| 102 | - res.config.headers['Authorization'] = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token 请根据实际情况自行修改 | |
| 103 | - resolve(service(res.config)) | |
| 104 | - }) | |
| 105 | - }) | |
| 76 | +service.interceptors.response.use(async res => { | |
| 77 | + // 未设置状态码则默认成功状态 | |
| 78 | + const code = res.data.code || 200; | |
| 79 | + // 获取错误信息 | |
| 80 | + const msg = res.data.msg || errorCode[code] || errorCode['default'] | |
| 81 | + if (ignoreMsgs.indexOf(msg) !== -1) { // 如果是忽略的错误码,直接返回 msg 异常 | |
| 82 | + console.log('132312311'); | |
| 83 | + return Promise.reject(msg) | |
| 84 | + } else if (code === 401) { | |
| 85 | + // 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了 | |
| 86 | + if (!isRefreshToken) { | |
| 87 | + isRefreshToken = true; | |
| 88 | + // 1. 如果获取不到刷新令牌,则只能执行登出操作 | |
| 89 | + if (!getRefreshToken()) { | |
| 90 | + return handleAuthorized(); | |
| 106 | 91 | } |
| 107 | - } else if (code === 500) { | |
| 108 | - Message({ | |
| 109 | - message: msg, | |
| 110 | - type: 'error' | |
| 111 | - }) | |
| 112 | - return Promise.reject(new Error(msg)) | |
| 113 | - } else if (code === 901) { | |
| 114 | - Message({ | |
| 115 | - type: 'error', | |
| 116 | - duration: 0, | |
| 117 | - dangerouslyUseHTMLString: true, | |
| 118 | - message: '<div>演示模式,无法进行写操作</div>' | |
| 119 | - + '<div> </div>' | |
| 120 | - + '<div>参考 https://doc.iocoder.cn/ 教程</div>' | |
| 121 | - + '<div> </div>' | |
| 122 | - + '<div>5 分钟搭建本地环境</div>', | |
| 123 | - }) | |
| 124 | - return Promise.reject(new Error(msg)) | |
| 125 | - } else if (code !== 200) { | |
| 126 | - if (msg === '无效的刷新令牌') { // hard coding:忽略这个提示,直接登出 | |
| 127 | - console.log('无效的刷新令牌') | |
| 128 | - } else { | |
| 129 | - Notification.error({ | |
| 130 | - title: msg | |
| 131 | - }) | |
| 92 | + // 2. 进行刷新访问令牌 | |
| 93 | + try { | |
| 94 | + const refreshTokenRes = await refreshToken() | |
| 95 | + // 2.1 刷新成功,则回放队列的请求 + 当前请求 | |
| 96 | + setToken(refreshTokenRes.data) | |
| 97 | + requestList.forEach(cb => cb()) | |
| 98 | + return service(res.config) | |
| 99 | + } catch (e) {// 为什么需要 catch 异常呢?刷新失败时,请求因为 Promise.reject 触发异常。 | |
| 100 | + // 2.2 刷新失败,只回放队列的请求 | |
| 101 | + requestList.forEach(cb => cb()) | |
| 102 | + // 提示是否要登出。即不回放当前请求!不然会形成递归 | |
| 103 | + return handleAuthorized(); | |
| 104 | + } finally { | |
| 105 | + requestList = [] | |
| 106 | + isRefreshToken = false | |
| 132 | 107 | } |
| 133 | - return Promise.reject('error') | |
| 134 | 108 | } else { |
| 135 | - return res.data | |
| 109 | + // 添加到队列,等待刷新获取到新的令牌 | |
| 110 | + return new Promise(resolve => { | |
| 111 | + requestList.push(() => { | |
| 112 | + res.config.headers['Authorization'] = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token 请根据实际情况自行修改 | |
| 113 | + resolve(service(res.config)) | |
| 114 | + }) | |
| 115 | + }) | |
| 116 | + } | |
| 117 | + } else if (code === 500) { | |
| 118 | + Message({ | |
| 119 | + message: msg, | |
| 120 | + type: 'error' | |
| 121 | + }) | |
| 122 | + return Promise.reject(new Error(msg)) | |
| 123 | + } else if (code === 901) { | |
| 124 | + Message({ | |
| 125 | + type: 'error', | |
| 126 | + duration: 0, | |
| 127 | + dangerouslyUseHTMLString: true, | |
| 128 | + message: '<div>演示模式,无法进行写操作</div>' | |
| 129 | + + '<div> </div>' | |
| 130 | + + '<div>参考 https://doc.iocoder.cn/ 教程</div>' | |
| 131 | + + '<div> </div>' | |
| 132 | + + '<div>5 分钟搭建本地环境</div>', | |
| 133 | + }) | |
| 134 | + return Promise.reject(new Error(msg)) | |
| 135 | + } else if (code !== 200) { | |
| 136 | + if (msg === '无效的刷新令牌') { // hard coding:忽略这个提示,直接登出 | |
| 137 | + console.log(msg) | |
| 138 | + } else { | |
| 139 | + Notification.error({ | |
| 140 | + title: msg | |
| 141 | + }) | |
| 136 | 142 | } |
| 137 | - }, | |
| 138 | - error => { | |
| 143 | + return Promise.reject('error') | |
| 144 | + } else { | |
| 145 | + return res.data | |
| 146 | + } | |
| 147 | +}, error => { | |
| 139 | 148 | console.log('err' + error) |
| 140 | - let { message } = error; | |
| 149 | + let {message} = error; | |
| 141 | 150 | if (message === "Network Error") { |
| 142 | 151 | message = "后端接口连接异常"; |
| 143 | - } | |
| 144 | - else if (message.includes("timeout")) { | |
| 152 | + } else if (message.includes("timeout")) { | |
| 145 | 153 | message = "系统接口请求超时"; |
| 146 | - } | |
| 147 | - else if (message.includes("Request failed with status code")) { | |
| 154 | + } else if (message.includes("Request failed with status code")) { | |
| 148 | 155 | message = "系统接口" + message.substr(message.length - 3) + "异常"; |
| 149 | 156 | } |
| 150 | 157 | Message({ | ... | ... |