• token过期 如何使用refresh_token实现无感刷新页面?


    步骤如下:

    1-token过期根据refresh_token获取新的token 重新获取数据

    2-创建一个新的axios实例 【使用request防止再次进入请求拦截和请求响应而进入死循环】

    3-根据请求相应的响应值 是不是401 是:说明token过期

    然后进行判断store中的 user :{token:’*****’,refresh_token:’******’}中的 refresh_token和user对象是否存在 ,如果不存在说明之前没有登录过,直接去登录

    4-使用新创建的axios 实例对象 requestFreshToken 发送新的请求 headers中的口令携带的是 refresh_token

    5-获取token之后 将值重新赋值给user中的token

    6-将user重新存入store中

    7-重新获取刚才因为token失效而没有获取的数据 直接使用request 参数 来自error对象中【这里保存了之前token失效的请求数据】

    具体实现 代码如下:

    1. import Vue from 'vue'
    2. import axios from 'axios'
    3. import router from '@/router'
    4. import {
    5. ACCESS_TOKEN,
    6. FRESH_TOKEN
    7. } from '@/store/mutation-types'
    8. import {
    9. Message
    10. } from 'element-ui';
    11. // somefile.js
    12. import ls from '@/utils/localStore.js';
    13. const defaultSettings = require("@/settings.js");
    14. let apiBaseUrl = process.env.VUE_APP_BASE_API
    15. let isRefreshing = false //是否正在刷新token
    16. let callbacks = [] //失效后同时发送请求的容器 --- 缓存接口
    17. // 刷新 token 后, 将缓存的接口重新请求一次
    18. function onAccessTokenFetched() {
    19. callbacks.forEach(callback => {
    20. callback()
    21. })
    22. callbacks = [] // 清空缓存接口
    23. }
    24. // 添加缓存接口
    25. function addCallbacks(callback) {
    26. callbacks.push(callback)
    27. }
    28. // 请求函数
    29. function request(url, options) {
    30. const token = ls.get(ACCESS_TOKEN)
    31. const defaultOptions = {
    32. withCredentials: true,
    33. url: url,
    34. baseURL: apiBaseUrl,
    35. };
    36. const newOptions = {
    37. ...options,
    38. ...defaultOptions
    39. };
    40. newOptions.headers.token = token;
    41. return axios.request(newOptions)
    42. .then(checkStatus)
    43. .catch(error => console.log(error));
    44. }
    45. function checkStatus(error) {
    46. if (error.response) {
    47. const response = error.response
    48. const refreshToken = ls.get(FRESH_TOKEN);
    49. if (response && response.status == 401) {
    50. // 刷新token的函数,这需要添加一个开关,防止重复请求
    51. if (!isRefreshing) {
    52. isRefreshing = true;
    53. axios({
    54. baseURL: apiBaseUrl,
    55. url: `/reLogin/${refreshToken}`,
    56. method: 'post'
    57. }).then(response => {
    58. const res = response.data;
    59. isRefreshing = false;
    60. if (res.code == '200') {
    61. ls.set(ACCESS_TOKEN, res.data.access_token)
    62. onAccessTokenFetched()
    63. } else {
    64. // 登出
    65. ls.clear()
    66. router.replace({
    67. path: '/login'
    68. })
    69. }
    70. }).catch(error => {
    71. console.log("刷新token异常", error)
    72. // 跳转到首页
    73. ls.clear()
    74. console.log('request router', router)
    75. router.replace({
    76. path: '/login'
    77. })
    78. });
    79. }
    80. isRefreshing = true;
    81. const options = response.config;
    82. const url = options.url.replace(process.env.VUE_APP_BASE_API, '')
    83. // 这个Promise函数很关键
    84. const retryOriginalRequest = new Promise((resolve) => {
    85. console.log('resolve', resolve)
    86. addCallbacks(() => {
    87. resolve(request(url, options))
    88. })
    89. });
    90. return retryOriginalRequest;
    91. } else {
    92. // message 诺到里面,401不报错
    93. Message.closeAll()
    94. Message({
    95. message: response.data.msg,
    96. type: 'error'
    97. }, true)
    98. return Promise.reject(error)
    99. }
    100. }
    101. return error.data;
    102. // return error;
    103. }
    104. // 创建一个axios实例
    105. const service = axios.create({
    106. baseURL: apiBaseUrl,
    107. withCredentials: true, // 跨域请求时发送Cookie
    108. timeout: 50000 // request timeout
    109. })
    110. //请求拦截器
    111. service.interceptors.request.use(
    112. config => {
    113. // 在发送请求之前做一些事情
    114. if (ls.get(ACCESS_TOKEN)) {
    115. // 让每个请求都带有token
    116. config.headers['token'] = ls.get(ACCESS_TOKEN)
    117. } else if (process.env.NODE_ENV === 'development' && defaultSettings.noToken) {
    118. // console.log('没有token--------', process.env.NODE_ENV)
    119. config.headers['swagger_user_name'] = defaultSettings.swagger_user_name
    120. config.headers['swagger_user_pwd'] = 1
    121. }
    122. config.autoCatchErr = true;
    123. return config
    124. },
    125. error => {
    126. console.log(error) // for debug
    127. return Promise.reject(error)
    128. }
    129. )
    130. // 响应拦截器
    131. service.interceptors.response.use(
    132. response => {
    133. const res = response.data;
    134. // 增加res.response,zq-el-ui中的下载请求会用到
    135. res.response = response;
    136. if (response.status == 200 && response.config.params && response.config.params.no_interception_response) {
    137. return response.data
    138. }
    139. // 文件下载
    140. if (response.status == 200 && response.request.responseType == "blob" || response.request.responseType == "arraybuffer") {
    141. return response.data
    142. }
    143. // 正常返回
    144. if (response.data.body && response.data.body.rtnCode === '0000') {
    145. return response.data.body.dataSet
    146. }
    147. if (res.code == 200) {
    148. if (res.msg) {
    149. Message({
    150. message: res.msg,
    151. type: 'success'
    152. }, true)
    153. }
    154. return res
    155. } else {
    156. if (response.config.autoCatchErr) {
    157. Message.closeAll()
    158. Message({
    159. message: res.msg,
    160. type: 'error'
    161. }, true)
    162. console.log('请求失败', res)
    163. //
    164. // throw new Error('接口报错:::', res);
    165. return res
    166. } else {
    167. Message({
    168. message: res.msg,
    169. type: 'error'
    170. }, true)
    171. return res
    172. }
    173. }
    174. },
    175. error => {
    176. return checkStatus(error)
    177. }
    178. )
    179. export default service

  • 相关阅读:
    vue组件缓存
    初探富文本之基于虚拟滚动的大型文档性能优化方案
    AutoSAR入门:开发工具链介绍
    超级明星们的人物化身 NFT 将来到 The Sandbox 元宇宙
    ADRC/Matlab一步步实现跟踪微分器TD(附完整PLC测试代码链接)
    yaml基础知识
    手写一个自己的mystrstr
    【JavaScript脚本宇宙】交互无限可能:探索JavaScript库的交互性魔力
    论文分享:Generating Playful Palettes from Images
    C++ 内联函数详解
  • 原文地址:https://blog.csdn.net/qq_43474235/article/details/127836995