退出登录通用方案

702 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第11天,点击查看活动详情

前言

退出登录是前端经常使用的功能,一般分为用户主动退出和用户被动退出

当用户退出时,需要把当前用户的缓存数据全部清除后返回登陆页面

主动退出

主动退出只有用户点击退出登录按钮一种情况

2.png

在vuex处理退出操作,因为用户数据都保存在vuex中,需要以下操作

  1. 清除token
  2. 清空用户信息
  3. 清空本地存储
  4. 跳转登录页

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')
}

被动退出

用户被动退出有以下情况

  1. token失效
  2. 多人同时登录一个账号,只能单点登录

token失效

通常token的时效由后端处理,但是前端也可以对token时效进行处理,使用户的信息更加安全

在用户登陆时,可以记录用户登录的时间,之后在用户调用接口时,在请求拦截器中判断当前时间和登录时间的差值是否超过了token时效,如果超过则强制退出。

新建util/auth.js,需要声明三个函数

  1. 保存登录时间
  2. 获取登录时间
  3. 判断是否超时
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))
  }
)