網站首頁 編程語言 正文
401狀態碼的含義和處理
401狀態碼的含義
axios向服務器端發送請求時,有兩種情況會出現401狀態碼(unauthorized未授權):
1. 服務端要求傳遞token信息,而實際發送請求時沒有傳遞。
2. 發送請求時有傳遞token到達服務器端,但由于時間比較久,這個token在服務器中已經過期了(服務器存儲token有效期時間為2個小時)。
總之,服務器端有些api接口要求傳遞token,token失效或沒有傳遞,就會報401錯誤。
401狀態碼的處理
1. 在axios請求攔截器中做token傳遞操作。
2. 可以這樣設置,在axios響應攔截器中判斷請求狀態如果是401,就強制用戶重新登錄系統。
第2種情況處理實現:
在axios的響應攔截器中,判斷錯誤碼等于401就強制登錄(utils/ax.js)
// 引入路由 import router from '@/router' // 配置響應攔截器 axios.interceptors.response.use(function (response) { ? // 正常響應處理 ? return response }, function (error) { ? // 非正常響應處理(包括401) ? // console.dir(error) // 對象: config request response isAxiosError toJSON ? if (error.response.status === 401) { ? ? // token失效(token在服務器端已經失效了,2個小時時效) ? ? // 強制用戶重新登錄系統,以刷新服務器端的token時效 ? ? router.push('/login') ? ? // 不要給做錯誤提示了 ? ? return new Promise(function () {}) // 空的Promise對象,沒有機會執行catch,進而不做錯誤提示了 ? } ? // return new Promise((resolve,reject)=>{ ? // reject('獲得文章失敗!') ? // }) ? return Promise.reject(error) })
注意:
1. 路由對象.push(xxx) 可以實現編程式導航。
2. 路由對象:在組件中是 this.$router ,在main.js/ax.js文件中就是router對象(需要import導入)。
模擬服務器端token失效步驟:
1. 刪除客戶端sessionStorage數據。
2. 暫時屏蔽守衛代碼(開發完畢再打開)。
401狀態碼升級處理
401狀態碼
axios向服務器端發送請求時有兩種情況會出現401狀態碼(unauthorized未授權):
1. 服務端要求傳遞token信息,而實際沒有傳遞。
2. 有傳遞token到達服務器端,但由于時間比較久,這個token在服務器中已經過期了(服務器存儲token有效期時間為2個小時)。
總之,服務器端有些api接口要求傳遞token,token失效或沒有傳遞,就會報401錯誤。
相關處理
1. 第1種情況,可以在axios請求攔截器中做token傳遞操作。
2. 第2種情況,之前是這樣處理的,在axios響應攔截器中判斷請求狀態如果是401,就強制用戶重新登錄系統
這樣處理用戶體驗非常不好,現在做一次升級優化處理。?
服務器端返回兩個秘鑰信息,它們在服務端都有使用時效:
-
token
有效期2小時。 -
refresh_token
有效期14天,refresh_token用于在token過期后,重新獲取并刷新token時效使用的。
針對第2種401狀態碼處理步驟為:
1. 判斷refresh_token是否存在
不存在就直接重新登錄。
存在,axios發起請求,帶著refresh_token請求服務端,獲取新token出來:
成功:對vuex和localStorage進行token信息更新。
失?。呵蹇諢o效用戶信息,直接重新登錄。
示例代碼1?
// 響應攔截器 (響應成功:剝離無效數據,響應失?。核⑿聇oken) instance.interceptors.response.use(res => { // 將來獲取數據:res.data.data 麻煩 // 想要結果:data 即可 try { return res.data.data } catch (e) { return res } }, async err => { try { // 目的:刷新token if (err.response && err.response.status === 401) { // 未登錄 跳轉登錄頁面 阻止程序運行 const { user } = store.state // 如果沒有token沒登錄 如果沒有refresh_token無法刷新token if (!user.token || !user.refresh_token) { router.push('/login') return Promise.reject(err) } // 刷新token,發請求,沒有配置的axios,自己配置refresh_token const res = await axios({ url: 'http://ttapi.research.itcast.cn/app/v1_0/authorizations', method: 'put', headers: { Authorization: `Bearer ${user.refresh_token}` } }) // token獲取 res.data.data.token // 更新 vuex 和 本地 token store.commit('setUser', { token: res.data.data.token, refresh_token: user.refresh_token }) // 繼續發送剛才錯誤的請求 // instance({之前錯誤的請求配置}) // err錯誤對象 包含(response 響應對象 |config 請求配置) return instance(err.config) } } catch (e) { // exception 異常 // 刷新token失敗 router.push('/login') return Promise.reject(e) } return Promise.reject(err) })
演示代碼:promise錯誤處理:
示例代碼2
import store from '@/store' // 引入vuex中的store實例 import router from '@/router' // 引入路由對象實例 …… // 響應攔截器 instance.interceptors.response.use( function (response) { try { // 返回具體有價值的業務數據 return response.data.data } catch (error) { return response.data } }, async function (error) { // 響應有錯誤,有可能錯誤狀態碼為401 if (error.response && error.response.status === 401) { // 定義登錄路由對象 let toPath = { name: 'login', query: { redirectUrl: router.currentRoute.path } } // 跳轉對象 // 如果refresh_token不存在 if (!store.state.user.refresh_token) { router.push(toPath) return Promise.reject(error) } try { // 刷新用戶token // 應該發送一個請求 換取新的token // 這里不應該再用instance 因為 instance會再次進入攔截器 用默認的axios let result = await axios({ method: 'put', url: 'http://ttapi.research.itcast.cn/app/v1_0/authorizations', headers: { Authorization: `Bearer ${store.state.user.refresh_token}` } }) // 獲取到新token后,就對vuex和localStorage進行更新 store.commit('updateUser', { token: result.data.data.token, // 拿到新的token之后 refresh_token: store.state.user.refresh_token // 將之前 refresh_token 14天有效期 }) return instance(error.config) // 把剛才錯誤的請求再次發送出去 然后將promise返回 } catch (err) { // 如果錯誤 表示補救措施也沒用了(有可能refresh_token也失效了) // 應該跳轉到登錄頁 并且 把廢掉的用戶信息全都干掉 store.commit('clearUser') // 所有的用戶信息清空 router.push(toPath) // 跳轉到回登錄頁 return Promise.reject(err) } } return Promise.reject(error) } ) ') // 所有的用戶信息清空 router.push(toPath) // 跳轉到回登錄頁 return Promise.reject(err) } } return Promise.reject(error) } )
原文鏈接:https://blog.csdn.net/jyn15159/article/details/108879988
相關推薦
- 2022-06-21 .NET?Core?API之格式化輸出對象OutputFormatter_實用技巧
- 2022-04-08 Swift使用表格組件實現單列表_Swift
- 2022-05-06 SQL獲取數據庫中表信息:表名、建表時間、總行數、數據大小等
- 2022-05-12 Echarts x軸標簽太長解決方案
- 2022-11-04 C++多態特性之派生與虛函數與模板詳細介紹_C 語言
- 2024-04-03 clickhouse報Ports are not available
- 2022-10-15 Nginx如何配置加密證書訪問實現_nginx
- 2022-08-03 Python?權限控制模塊?Casbin_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支