今天和大家分享一下 token 失效的处理方式
面试官:说说token失效的处理方式
·
思路
1. token产生(存入本地)时的时间戳:用户成功登录,存token时记下此刻的时间戳A
2.token使用的时间戳:axios的请求拦截器中,请求会自动携带token,这就是使用token的时候,记下此刻的时间戳B
3.检查是否过期:时间差 = 时间戳B - 时间戳A
,将时间差与指定的token有效时长对比。如果大于有效时长,表示已经过期;如果小于有效时长,表示没过期
4.不同情况的处理
-
已经过期:
- 退出登录--清空token、当前用户信息,跳转到登录页
- 更换token
-
没过期:业务照常进行
那么废话不多说,我把代码给大家参考一下
- 定义工具函数(先装包
js-cookie
)
/* src/utils/auth.js */
import Cookies from 'js-cookie'
// 定义时间戳的key
const timeKey = 'hr-timestamp'
// 存时间戳
export function setTimeStamp() {
return Cookies.set(timeKey, Date.now())
}
// 读时间戳
export function getTimeStamp() {
return Cookies.get(timeKey)
}
- 到Vuex中的登录函数中,记下登录成功时的时间戳
import { setTimeStamp } from '@/utils/auth.js'
const actions = {
/* 一、定义函数:用户登录 */
/* 调用处:点击登录按钮时 */
async login(context, payload) {
// 1.发请求
const res = await loginApi(payload)
// 2. 存登录成功后的token ,token在响应数据res.data中
context.commit('SET_TOKEN', res.data)
// 3. token过期的主动处理:记下存token时的时间戳
setTimeStamp()
}
}
- 到
request.js
中,定义过期时长、判断过期函数
/* src/utils/request.js */
import store from '@/store'
import { getTimeStamp } from '@/utils/auth'
import router from '@/router'
// 定义过期时长
const TimeOut = 3600 // 单位:秒
// 定义判断过期函数
function checkTimeOut() {
// 当前时间
const currentTime = Date.now()
// 读取存token时的时间戳
const timeStamp = getTimeStamp()
// 转换为秒后再比较
const flag = ((currentTime - timeStamp) / 1000) > TimeOut
// 返回布尔值
return flag
}
- 到
request.js
的请求拦截器中,编写业务逻辑
service.interceptors.request.use(
(config) => {
const token = store.getters.token // 尝试读取token
if (token) {
/* token过期的主动处理 */
if (checkTimeOut()) {
/* return的flag为false,表示过期 */
// 触发actions中的logout函数,清空当前过期的token(防止页面跳转错误)、清空用户信息
store.dispatch('user/logout')
// 跳转到登录页
router.push({ path: '/login' })
// return抛出一个执行错误, 用于终止promise的执行链
return Promise.reject(new Error('token超时,请重新登录'))
}
// 如果token存在,就自动添加到请求头上
// 注意:使用动态添加属性的形式。
// 原因:如果headers中的Authorization之前不存在,这样能添加一个新属性;如果headers中的Authorization之前存在,这样能覆盖以前的token值
config.headers['Authorization'] = `Bearer ${token}`
}
return config
},
(error) => {
return Promise.reject(error)
}
)
被动处理
被动处理:主要是后端的活儿,服务端处理token过期问题
思路
- 每次请求成功发送后,都会得到服务器的响应。经过后端的判断,如果当前的token失效,那么一定会在响应的数据中携带一个标识。或者说返回一个错误状态码,例如
code:233333
- token过期属于响应失败,axios响应拦截器中的第二个回调会被触发
- 在响应拦截器的第二个回调中,编写token失效的业务逻辑:清除当前的失效token(防止页面无法跳转);跳转到登录页;return一个执行错误,用于终止当前的promise执行链
service.interceptors.response.use(
(response) => {
// dosomething
},
(error) => {
// ! 服务器响应失败时,干些事情: 导致响应失败的原因有很多,其中之一是 token 过期
// 响应失败时的error(错误对象),它经过了axios的2层包装,服务器响应的真实数据在 error.response.data 中。
// axios包装的提示信息是:error.message,与服务器响应的真实数据是两回事
const realData = error.response.data
/* 处理token失效---后端处理 */
if (error.response && realData && realData.code === 233333) {
// 以上三个条件全部满足时,才说明token超时
// 1. 触发actions中的logout函数,清除无效token、当前用户信息
store.dispatch('user/logout')
// 2. 跳转到登录页面
router.push({ path: '/login' })
// 3. return 一个执行错误,用于终止当前的promise执行链
return Promise.reject(error)
} else {
/* 如果token未失效,则是其他错误 */
// 1. 提示错误信息
Message.error(realData.message)
// 2. return 一个执行错误
return Promise.reject(error)
}
}
)
本文参考我的一个朋友,他的文章也非常值得一看。
更多推荐
已为社区贡献9条内容
所有评论(0)