退出登錄觸發時機一般有兩種:
1.主動退出:用戶點擊退出登錄按鈕后退出
2.被動退出:token過期,或被人“頂號”退出
無論是什么退出方式,在用戶退出時,所需要執行的操作都是固定的:
1.清理掉當前用戶的緩存數據
2.清理掉相關權限的配置
3.返回到登錄頁面
用戶主動退出登錄功能實現
logout() {
// 清除vuex緩存,初始化用戶信息與token
this.commit('user/setToken', '')
this.commit('user/setUserInfo', {})
// 清除loacalhost緩存
remoAllItem()
// 跳轉到登錄頁
router.push('/login')
}
用戶被動退出登錄功能實現
場景1:token失效
場景2:單用戶登錄,其他人登錄該賬號,被頂號
處理方案:
- 主動處理方案:應對token失效,toekn是有時效性的,這個時效都是在服務端進行處理的。
- 在用戶登錄時,記錄當前的登錄時間
- 制定一個時效時長
- 在接口調用時,根據當前時間對比登錄時間,看是否超過了時效時間
如果未超過,則正常進行后續操作
如果超過,則進行退出登錄操作
auth.js:
import {
TIME_STAMP,
TOKEN_TIMEOUT_VALUE
} from '@/constant'
import {
setItem,
getItem
} from '@/utils/storage'
/**
* 獲取時間戳
*/
export function getTimeStamp() {
return getItem(TIME_STAMP)
}
/**
* 設置時間戳
*/
export function setTimeStamp() {
setItem(TIME_STAMP, Date.now())
}
/**
* 是否超時
*/
export function isCheckTimeout() {
// 當前時間戳
var currentTime = Date.now()
// 緩存時間戳
var timeStamp = getTimeStamp()
return currentTime - timeStamp > TOKEN_TIMEOUT_VALUE
}
constance.js:
// token 時間戳
export const TIME_STAMP = 'timeStamp'
// 超時時長(毫秒) 兩小時
export const TOKEN_TIMEOUT_VALUE = 2 * 3600 * 1000
登錄成功,緩存token后,緩存token保存的時間:
import {
setTimeStamp
} from '@/utils/auth'
login({
username,
password: md5(password)
})
.then(data => {
this.commit('user/setToken', data.token)
// 用緩存記錄下token保存的時間
setTimeStamp()
resolve()
})
.catch(err => {
reject(err)
})
request.js:
import {
isCheckTimeout
} from '@/utils/auth'
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 5000
})
// 請求攔截器
service.interceptors.request.use(
config => {
// 添加 icode
config.headers.icode = '5FD82D1BDB03DBD2'
// 在這個位置需要統一的去注入token
if (store.getters.token) {
// 每次發起請求,查看token是否已經過期
if (isCheckTimeout()) {
// 如果已經過期,執行登出
store.dispatch('user/logout')
// 這里拋出的錯誤,會在響應攔截器的錯誤捕捉中捕捉到
return Promise.reject(new Error('token 失效'))
}
// 如果token存在 注入token
config.headers.Authorization = `Bearer ${store.getters.token}`
}
// 必須返回 config
return config
},
error => {
return Promise.reject(error)
}
)
- 被動處理方案:應對token失效與單用戶登錄
- 服務端返回數據時,會通過特定狀態碼通知前端
- 當前端接收到特定狀態碼時,表示遇到了特定狀態:token時效或單用戶登錄
- 此時進行退出登錄處理
// 響應攔截器
service.interceptors.response.use(
response => {
const {
success,
message,
data
} = response.data
// 要根據success的成功與否決定下面的操作
if (success) {
return data
} else {
// 業務錯誤
ElMessage.error(message) // 提示錯誤消息
return Promise.reject(new Error(message))
}
},
error => {
// 如果被頂號,主動退出登陸
if (
error.response &&
error.response.data &&
// 這里的狀態碼對應到被頂號,如果被頂號
error.response.data.code === 401
) {
// 退出登錄
store.dispatch('user/logout')
}
ElMessage.error(error.message) // 提示錯誤信息
return Promise.reject(error)
}
)