Token 失效的介入
- 主动介入
- 被动介入
开门的钥匙不是一直有效的,如果一直有效,会有安全风险,所以我们尝试在客户端进行一下token的时间检查
主动介入--思路
-
token产生(存入本地)时的时间戳:用户成功登录,存token时记下此刻的时间戳A
2.token使用的时间戳:axios的请求拦截器中,请求会自动携带token,这就是使用token的时候,记下此刻的时间戳B
3.检查是否过期:
时间差 = 时间戳B - 时间戳A,将时间差与指定的token有效时长对比。如果大于有效时长,表示已经过期;如果小于有效时长,表示没过期
4.不同情况的处理
- 已经过期:
- 退出登录--清空token、当前用户信息,跳转到登录页
- 更换token
- 没过期:业务照常进行
后端介入--思路
被动处理:主要是后端的活儿,服务端处理token过期问题
- 每次请求成功发送后,都会得到服务器的响应。经过后端的判断,如果当前的token失效,那么一定会在响应的数据中携带一个标识。或者说返回一个错误状态码,例如
code:233333 - token过期属于响应失败,axios响应拦截器中的第二个回调会被触发
- 在响应拦截器的第二个回调中,编写token失效的业务逻辑:清除当前的失效token(防止页面无法跳转);跳转到登录页;return一个执行错误,用于终止当前的promise执行链
一般情况下,token过期,当用户操作页面的时候检查token是否过期,如果过期了则跳转到登录页面,
一般对于token过期的处理方式有两种:
方式一:主动介入(前端主动介入)
主动介入就是前端给token设定一个过期时间,这个主要是考虑网站安全,因此才要设置过期时间。
比如:前端可以设定过期时间为5秒,方便测试,
那么问题来了???如何知道登录之后过了多长时间呢?
答:我们可以这样做,首先在登录那一刻,把那一刻的时间戳(毫秒保存起来)然后在用户操作页面的时候再次获取时间戳,然后取用户操作页面时的时间戳减去登录的时间戳,此刻得到一个时间差(这个时间差就是用户登录该网站的时长),当这个时间差大于5秒,则表示token过期了,否则没有过期。------这就是前端主动介入的逻辑
1、登录的时间戳=>在登录的时候可以保存本地
2、当前时间戳为用户点击按钮,需要发送请求的时候=>在请求拦截器可添加
if (res) {
// 登录成功弹窗提示用户
Message.success('登录成功')
store.commit('setToken', res)
// 保存当前时间戳
localStorage.setItem('loginTime', Date.now())
// 登录成功跳转首页
router.push('/')
} else {
// 登录失败弹窗提示
Message.error(res.data.message)
}
},
2.在请求拦截器中,获取注入token的时候,检查时间戳,且定个常量,token失效的时间为1个小时也就是1* 60 * 60 = 3600s,这样就有一个公式 时间差 = 当前的时间戳 - 在注入token的时间戳 如果这个时间差 大于 设置的 token存在的时间 那么token就是失效了 那么在下次请求的时候会 =>退出页面 加上登出操做()重新登录获取token 且提示消息告诉用户token失效
import { getTimeStamp } from '@/utils/auth'
// token存一个时间为5秒 5s
const time = 5000
request.interceptors.request.use(config => {
...........
// 有token才会有时间戳计算
if (store.getters.token) {
const nowTime = Date.now() // 获取当前时间戳
const loginTimeS = localStorage.getItem('loginTime') //把在用户登录时候存在本地的时间戳 取出来
if (nowTime - loginTimeS > time ) {
//如果两者时间差大于设定的时间 就表示token过期
// 调用登出状态 销毁token 以及获得的用户信息等 且重置数据
store.dispatch('user/lgOut')
// 进入登录页面
router.push('/login')
// 超时了 打回去且 提示消息
return promise.reject(new Error('token超时了'))
}
}
})
方式二:被动介入(后端设置好了token过期时间)
当token过期的时候,我们调用接口时,后端会返回一个转态码给我们,当这个转态码为10002(这个10002是后端会给到前端的)---发起请求服务器响应给到我们--所以实在响应拦截器设置即可
除了token的主动介入之外,我们还可以对token进行被动处理,如图
error => {
console.log(82, err)
console.dir(err)
// error 信息 里面 response的对象
if (error.response && error.response.data && error.response.data.code === 10002) {
// 当等于10002的时候 表示 后端告诉我token超时了
store.dispatch('user/logout') // 登出action 删除token
router.push('/login')
} else {
Message.error(error.message) // 提示错误信息
}
return Promise.reject(error)
}