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
- 響應式Web設計Web
- 響應式 Web 設計技巧Web
- Vue響應式—-資料響應式原理Vue
- Vue響應式----資料響應式原理Vue
- 使用Reactor響應式程式設計React程式設計
- 響應式程式設計RxJava (一)程式設計RxJava
- 響應式程式設計總覽程式設計
- 響應式程式設計一覽程式設計
- 響應式網頁設計示例網頁
- 讓 Weex UI 響應系統設定UI
- 響應式設計?響應式設計的基本原理是什麼?如何做?
- 函式響應式程式設計與RxSwift函式程式設計Swift
- 自適應網頁設計/響應式Web設計網頁Web
- 響應式程式設計入門(RxJava)程式設計RxJava
- 響應式程式設計庫RxJava初探程式設計RxJava
- 淺談前端響應式設計(一)前端
- 淺談前端響應式設計(二)前端
- iPhone X 響應式網頁設計iPhone網頁
- 漫談響應式網頁設計網頁
- 響應式導航設計案例解析
- [譯]函式式響應程式設計入門指南函式程式設計
- 在 js 裡定義按鈕的響應函式JS函式
- 響應式程式設計簡介之:Reactor程式設計React
- 響應式程式設計機制總結程式設計
- 十大響應式Web設計框架Web框架
- 響應式Web設計實戰總結Web
- Tailwind CSS 響應式設計實戰指南AICSS
- 《學習響應式設計》作者Clarissa Peterson:響應式設計並不是萬能的(圖靈訪談)圖靈
- iOS 函式響應式程式設計 (ReactiveCocoa)– 前篇iOS函式程式設計React
- 自己實現一個VUE響應式--VUE響應式原理Vue
- HTML5—-響應式(自適應)網頁設計HTML網頁
- 響應式前端框架前端框架
- 響應式影象教程
- 響應式影像教程
- 響應式佈局