退出登录方案实现
退出登录触发时机一般有两种:
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) } )