开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第11天,点击查看活动详情
前言
退出登录是前端经常使用的功能,一般分为用户主动退出和用户被动退出
当用户退出时,需要把当前用户的缓存数据全部清除后返回登陆页面
主动退出
主动退出只有用户点击退出登录按钮一种情况
在vuex处理退出操作,因为用户数据都保存在vuex中,需要以下操作
- 清除token
- 清空用户信息
- 清空本地存储
- 跳转登录页
在actions中声明logout方法
user.js
import { setItem, getItem, removeAllItem } from '@/utils/storage'
import { TOKEN } from '@/constant'
import router from '@/router'
import { setTimeStamp } from '@/utils/auth'
export default {
namespaced: true,
state: () => ({
token: getItem(TOKEN) || '',
userInfo: {}
}),
mutations: {
setToken(state, token) {
state.token = token
setItem(TOKEN, token)
},
setUserInfo(state, userInfo) {
state.userInfo = userInfo
}
},
actions: {
logout() {
this.commit('user/setToken', '')
this.commit('user/setUserInfo', {})
// 清空本地存储
removeAllItem()
router.push('/login')
}
}
}
用户点击退出登录时触发该事件
import { useStore } from 'vuex'
const store = useStore()
const logout = () => {
store.dispatch('user/logout')
}
被动退出
用户被动退出有以下情况
- token失效
- 多人同时登录一个账号,只能单点登录
token失效
通常token的时效由后端处理,但是前端也可以对token时效进行处理,使用户的信息更加安全
在用户登陆时,可以记录用户登录的时间,之后在用户调用接口时,在请求拦截器中判断当前时间和登录时间的差值是否超过了token时效,如果超过则强制退出。
新建util/auth.js,需要声明三个函数
- 保存登录时间
- 获取登录时间
- 判断是否超时
import { TIME_STAMP } from '@/constant'
import { setItem } from '@/utils/storage'
// 记录登陆时间 用户登录时调用 在本地存储中保存
export function setTimeStamp() {
setItem(TIME_STAMP, Date.now())
}
import { TIME_STAMP } from '@/constant'
import { getItem } from '@/utils/storage'
// 获取登陆时间
export function getTimeStamp() {
return getItem(TIME_STAMP)
}
// token的时效 常量
import { TOKEN_TIMEOUT_VALUE } from '@/constant'
import { setItem, getItem } from '@/utils/storage'
// 判断是否超时
export function isCheckTimeout() {
// 当前时间
var currentTime = Date.now()
// 登陆时间
var timeStamp = getTimeStamp()
return currentTime - timeStamp > TOKEN_TIMEOUT_VALUE
}
在请求拦截器中对是否超时进行判断
import store from '@/store'
service.interceptors.request.use(
(config) => {
if (store.getters.token) {
if (isCheckTimeout) {
// 强制退出
store.dispatch('user/logout')
return Promise.reject(new Error('token失效'))
}
···
}
return config
},
(error) => {
return Promise.reject(error)
}
)
单点登录
单点登录一半在后端处理,如果同一个账号同时登陆,后端在返回数据时会携带特定状态码,在响应拦截器中判断是否含有特定状态码即可
import { ElMessage } from 'element-plus'
service.interceptors.response.use(
(response) => {
···
},
(error) => {
// token过期
if (
error.response &&
error.response.data &&
error.response.data.code === 特定状态码
) {
// 强制退出
store.dispatch('user/logout')
}
ElMessage.error(error.message)
return Promise.reject(new Error(error.message))
}
)