token響應式設定
處理使用者 Token
Token 是使用者登入成功之後服務端返回的一個身份令牌,在專案中的多個業務中需要使用到:
- 訪問需要授權的 API 介面
- 校驗頁面的訪問許可權
- …
但是我們只有在第一次使用者登入成功之後才能拿到 Token。
所以為了能在其它模組中獲取到 Token 資料,我們需要把它儲存到一個公共的位置,方便隨時取用。
往哪兒存?
- 本地儲存
- 獲取麻煩
- 資料不是響應式
- Vuex 容器(推薦)
- 獲取方便
- 響應式的
- 登入成功,將 Token 儲存到 Vuex 容器中
- 獲取方便
- 響應式
- 為了持久化,還需要把 Token 放到本地儲存
- 持久化
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
// 使用者的登入狀態資訊
user: JSON.parse(window.localStorage.getItem('TOUTIAO_USER'))
// user: null
},
mutations: {
setUser (state, user) {
state.user = user
window.localStorage.setItem('TOUTIAO_USER', JSON.stringify(user))
}
},
actions: {
},
modules: {
}
})
2、登入成功以後將後端返回的 token 相關資料儲存到容器中
async onLogin () {
// const loginToast = this.$toast.loading({
this.$toast.loading({
duration: 0, // 持續時間,0表示持續展示不停止
forbidClick: true, // 是否禁止背景點選
message: '登入中...' // 提示訊息
})
try {
const res = await login(this.user)
// res.data.data => { token: 'xxx', refresh_token: 'xxx' }
+ this.$store.commit('setUser', res.data.data)
// 提示 success 或者 fail 的時候,會先把其它的 toast 先清除
this.$toast.success('登入成功')
} catch (err) {
console.log('登入失敗', err)
this.$toast.fail('登入失敗,手機號或驗證碼錯誤')
}
// 停止 loading,它會把當前頁面中所有的 toast 都給清除
// loginToast.clear()
}
關於 Token 過期問題
登入成功之後後端會返回兩個 Token:
token
:訪問令牌,有效期2小時refresh_token
:重新整理令牌,有效期14天,用於訪問令牌過期之後重新獲取新的訪問令牌
我們的專案介面中設定的 Token
有效期是 2 小時
,超過有效期服務端會返回 401
表示 Token 無效或過期了。
為什麼過期時間這麼短?
- 為了安全,例如 Token 被別人盜用
過期了怎麼辦?
讓使用者重新登入,使用者體驗太差了- 使用
refresh_token
解決token
過期
如何使用 refresh_token
解決 token
過期?
處理邏輯
處理流程:
- 在axios的攔截器中加入token重新整理邏輯
- 當使用者token過期時,去向伺服器請求新的 token
- 把舊的token替換為新的token
- 然後繼續使用者當前的請求
在請求的響應攔截器中統一處理 token 過期:
* 封裝 axios 請求模組
*/
import axios from "axios";
import jsonBig from "json-bigint";
import store from "@/store";
import router from "@/router";
// axios.create 方法:複製一個 axios
const request = axios.create({
baseURL: "http://ttapi.research.itcast.cn/" // 基礎路徑
});
/**
* 配置處理後端返回資料中超出 js 安全整數範圍問題
*/
request.defaults.transformResponse = [
function(data) {
try {
return jsonBig.parse(data);
} catch (err) {
return {};
}
}
];
// 請求攔截器
request.interceptors.request.use(
function(config) {
const user = store.state.user;
if (user) {
config.headers.Authorization = `Bearer ${user.token}`;
}
// Do something before request is sent
return config;
},
function(error) {
// Do something with request error
return Promise.reject(error);
}
);
// 響應攔截器
request.interceptors.response.use(
// 響應成功進入第1個函式
// 該函式的引數是響應物件
function(response) {
// Any status code that lie within the range of 2xx cause this function to trigger
// Do something with response data
return response;
},
// 響應失敗進入第2個函式,該函式的引數是錯誤物件
async function(error) {
// Any status codes that falls outside the range of 2xx cause this function to trigger
// Do something with response error
// 如果響應碼是 401 ,則請求獲取新的 token
// 響應攔截器中的 error 就是那個響應的錯誤物件
console.dir(error);
if (error.response && error.response.status === 401) {
// 校驗是否有 refresh_token
const user = store.state.user;
if (!user || !user.refresh_token) {
router.push("/login");
// 程式碼不要往後執行了
return;
}
// 如果有refresh_token,則請求獲取新的 token
try {
const res = await axios({
method: "PUT",
url: "http://ttapi.research.itcast.cn/app/v1_0/authorizations",
headers: {
Authorization: `Bearer ${user.refresh_token}`
}
});
// 如果獲取成功,則把新的 token 更新到容器中
console.log("重新整理 token 成功", res);
store.commit("setUser", {
token: res.data.data.token, // 最新獲取的可用 token
refresh_token: user.refresh_token // 還是原來的 refresh_token
});
// 把之前失敗的使用者請求繼續發出去
// config 是一個物件,其中包含本次失敗請求相關的那些配置資訊,例如 url、method 都有
// return 把 request 的請求結果繼續返回給發請求的具體位置
return request(error.config);
} catch (err) {
// 如果獲取失敗,直接跳轉 登入頁
console.log("請求刷線 token 失敗", err);
router.push("/login");
}
}
return Promise.reject(error);
}
);
export default request;
相關文章
- 使用 setResponseStatus 函式設定響應狀態碼函式
- web app響應式字型設定!rem之我見WebAPPREM
- 函式響應式程式設計與RxSwift函式程式設計Swift
- 使用Reactor響應式程式設計React程式設計
- 讓 Weex UI 響應系統設定UI
- Vue響應式—-資料響應式原理Vue
- 響應式設計?響應式設計的基本原理是什麼?如何做?
- 淺談前端響應式設計(一)前端
- 淺談前端響應式設計(二)前端
- 響應式程式設計入門(RxJava)程式設計RxJava
- 響應式程式設計庫RxJava初探程式設計RxJava
- 在 js 裡定義按鈕的響應函式JS函式
- 響應式程式設計簡介之:Reactor程式設計React
- Responsive Web Design 響應式網頁設計Web網頁
- Tailwind CSS 響應式設計實戰指南AICSS
- 響應式程式設計機制總結程式設計
- 揚帆起航:從指令式程式設計到函式響應式程式設計程式設計函式
- 自己實現一個VUE響應式--VUE響應式原理Vue
- 完美解釋 Javascript 響應式程式設計原理JavaScript程式設計
- Ajax、JSON、響應式設計和Node.jsJSONNode.js
- 對響應式程式設計的懷疑 - lukaseder程式設計
- RxJS 系列故事(1)——理解響應式程式設計JS程式設計
- Kotlin Flow響應式程式設計,StateFlow和SharedFlowKotlin程式設計
- 響應式佈局
- 響應式前端框架前端框架
- 響應式影象教程
- 響應式影像教程
- 響應式變數變數
- Vue 響應式原理Vue
- 響應式導航
- 精講響應式WebClient第5篇-請求超時設定與異常處理Webclient
- 拼圖響應式前端框架版響應式後臺正式釋出前端框架
- 使用Java 9 Flow進行響應式程式設計Java程式設計
- ThinkPHP裡無法輸出圖片 設定響應頭PHP
- [譯] 響應式 Web 應用(四)Web
- [譯] 響應式 Web 應用(五)Web
- 什麼是響應式
- vue3 響應式Vue