1. 程式人生 > 其它 >token系統講解及過期處理

token系統講解及過期處理

token系統講解及過期處理:https://blog.csdn.net/qq_35942348/article/details/125971246

token系統講解及過期處理
1. token是什麼?用來做什麼
2. token儲存在哪?過期了怎麼辦?
3. 請求攔截與響應攔截執行時機(面試重點)
4. 解決token過期方案一: `重新登入`
5. 方案二:使用 `refresh_token` 方案


這玩意很簡單,記錄一下吧,給入門的小白用下
1. token是什麼?用來做什麼
token通常譯為令牌,暗號。舉個例子:我是古時候皇城中大內的高手(看門的大爺),進皇宮需要皇帝發的特製令牌,沒有指定的令牌是不能進的,我會把你攔住,說不定還會把你胖揍一頓。皇宮在這裡就相當於我們專案,為了專案的安全性,設定了這個token,進專案的人都需要有這個玩意,證明你有這個許可權。
token是怎麼生成的? 通過雜湊演算法(不常用)、uuid(雪花演算法,可保持全球唯一性),jwt工具等生成隨機字串(也可能會拼接上使用者的一些資訊)
為什麼token要有有效期?而且設定得這麼短? 為了提高token的安全性,不能永久有效,降低被別人劫持的風險
有時候登入的時候為什麼會有多個token?
1. 常規 token:使用頻繁,有效期比較短
2. refresh_token:當token過期的時候,用來得到新的token的,使用不頻繁,有效期比較長(一般為一個月)
我們怎麼知道token過期了? 通過調介面時返回的狀態碼,如果狀態碼是401(一般情況下),就說明沒有攜帶token,或者token過期了

2. token儲存在哪?過期了怎麼辦?
token由服務端生成,通過介面傳給前端。
一般在登入介面會給token值。
儲存看具體的專案場景,一般儲存在本地快取裡,有兩種方案供君選擇:
sessionStorage(會話級別,網頁一關就歇逼了)
localStorage(永久的,需要手動去清除)
token過期處理
重新登入 => 清空token,跳轉登入頁
refresh_token => 得到一個全新的token
3. 請求攔截與響應攔截執行時機(面試重點)
這玩意麵試問的多,看圖很清晰:

請求攔截器執行時機:axios呼叫之後,瀏覽器真正發起請求之前
響應攔截器執行時機:瀏覽器接受到響應資料之後,axios拿到資料之前
4. 解決token過期方案一: 重新登入
知道出現了401的錯誤: 使用響應攔截器
進行頁面的跳轉
此種方案使用者體驗不是很好(目前大部分企業及專案都這麼幹)
import store from '@/store'

// 響應攔截器
request.interceptors.response.use(
function (response) {
// 響應成功(響應狀態碼是 2xx)時執行第一個回撥函式
console.log('響應成功....')
return response
}, function (error) {
// 網路異常或響應失敗(響應狀態碼是非2開頭)時執行第二個回撥函式
console.log('響應失敗....')
// 1. 判斷響應的狀態碼是不是401,如果不是401就不用做任何處理
if (error.response && error.response.status === 401) {
// 2. 如果是401,就先清空token, 並跳轉到登入頁
store.commit('setUser', null)
router.push('/login')
}
return Promise.reject(error)
}
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
5. 方案二:使用 refresh_token 方案
判斷有沒有refresh_token,如果沒有跳轉登入頁
如果有refresh_token,呼叫重新整理token的介面,拿到新的token
更新vuex和loaclStoreage儲存的token
為原來呼叫介面方,重新去呼叫介面
如果利用refresh_token,重新整理token的介面失敗,則還是跳轉到登入頁
附上了詳細的註釋,講道理大佬們應該看得懂
import axios from 'axios'
import store from '@/store'
import router from '@/router'

const baseURL = 'http://xxx.xxx.net/'

const request = axios.create({
baseURL // 介面的基準路徑
})

// 請求攔截器
// Add a request interceptor
request.interceptors.request.use(function (config) {
// 請求發起會經過這裡
// config:本次請求的請求配置物件
const { user } = store.state
if (user && user.token) {
config.headers.Authorization = `Bearer ${user.token}`
}
// 注意:這裡務必要返回 config 配置物件,否則請求就停在這裡出不去了
return config
}, function (error) {
// 如果請求出錯了(還沒有發出去)會進入這裡
return Promise.reject(error)
})

request.interceptors.response.use(
function (response) {
// 響應成功(響應狀態碼是 2xx)時執行第一個回撥函式
return response
}, async function (error) {
// 網路異常或響應失敗(響應狀態碼是非2開頭)時執行第二個回撥函式
console.log('響應失敗時執行的程式碼....')
if (error.response && error.response.status === 401) {
const user = store.state.user
if (user && user.refresh_token) {
// 1. 判斷有沒有refresh_token,如果沒有跳轉登入頁
// 2. 如果有refresh_token,呼叫重新整理token的介面,拿到新的token
try {
var res = await axios({
baseURL: baseURL,
method: 'PUT',
url: '/xxx/xxx',
headers: {
Authorization: `Bearer ${user.refresh_token}`
}
})
} catch {
// 5. 如果refresh_token過期,進行清空token並跳轉到登入頁的處理
store.commit('setUser', null)
router.push('/login')
}

// 3. 更新vuex和loaclStoreage儲存的token
store.commit('setUser', {
refresh_token: user.refresh_token,
token: res.data.data.token
})
// 4. 為原來呼叫介面方,重新去呼叫介面
console.log(error.config)
return request(error.config)
} else {
// 1. 判斷有沒有refresh_token,如果沒有跳轉登入頁
store.commit('setUser', null)
router.push('/login')
}
}

// 3. 如果利用refresh_token,重新整理token的介面失敗,則還是跳轉到登入頁
// eslint-disable-next-line prefer-promise-reject-errors
return Promise.reject(error)
}
)

export default request
————————————————
版權宣告:本文為CSDN博主「歐陽呀」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本宣告。
原文連結:https://blog.csdn.net/qq_35942348/article/details/125971246