vue3 + Element-plus 开发后台管理系统(15)

395 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第15天,点击查看活动详情

搭建Layout架构 解决方案与实现

退出登录方案实现

退出登录,在前端来说其实是一种通用的实现方案,对于退出登录而言,他的触发时机一般有两种:

1、用户主动退出:用户点击退出登录按钮之后退出

2、用户被动退出:token 过期或者被其他用户顶下来时退出

不过,无论是那种方式的退出,其实在退出时都需要执行以下操作

1、清掉当前用户的缓存数据

2、清掉权限相关的配置

3、返回登录页

那么明确了对应的方案之后,我们就开始实现对应的功能

用户主动退出

store/modules/user.js 中,添加对应的 action

import router from '@/router'

logout() {
    this.commit('user/setToken', '')
    this.commit('user/setUserInfo', {})
    removeAllItem()
    router.push('/login')
}

为退出登录按钮添加事件,触发 logoutaction

import { useStore } from 'vuex'

const store = useStore()
const logout = () => {
  store.dispatch('user/logout')
}

至此,用户的主动退出功能我们就已经实现了

用户被动退出

针对用户的被动退出,其场景主要有两个

1、token 失效

2、其他人登录该账号被顶下

那么针对这两种场景,在前端对应的处理方案也分为两种

1、主动处理:主要应对 token 失效

2、被动处理:同时应对 token 失效与用户被顶下

这两种方式不是必须都要使用的,根据具体的业务场景有选择性的使用

  • 用户被动退出解决方案之主动处理

想要弄明白主动处理的方案,那么我们就得先搞明白对应的背景以及业务逻辑

我们先来说一说背景

我们知道 token 表示一个用户的身份令牌,对于服务端而言,它是只认令牌不认人的,所以说一旦其他人获得了你的 token,那么他就可以伪装成你,来获取对应的敏感数据。所以为了保证用户的信息安全,那么对于 token 而言就被制定了很多的安全策略

1、动态 token

2、刷新 token

3、时效 token

...

这些方案各有利弊,没有绝对完美的策略

而我们所选的方案就是时效 token

对于 token 本身是有时效的,这个大家肯定都知道。但是通常状况下,这个时效都是在服务端进行处理的,而这里我们要在服务端处理 token 时效的同时,在前端主动介入 token 时效的处理,从而保证用户信息更加的安全

那么我们对应的实现方案如下

1、在用户登录时,记录当前的登录时间

2、制定一个时效时长

3、在接口调用时,根据当前时间对比登录时间,查看是否超过了时效

(1)如果未超过,则进行后续操作

(2)如果超过,则进行退出操作

下边就来看看对应的代码

创建 utils/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
}

constant 中声明对应的变量

// token 时间戳
export const TIME_STAMP = 'timeStamp'
// 超时时长(毫秒) 两小时
export const TOKEN_TIMEOUT_VALUE = 2 * 3600 * 1000

在用户登录成功之后去设置时间,到 store/user.jslogin

import { setTimeStamp } from '@/utils/auth'

login(context, userInfo) {
  return new Promise((resolve, reject) => {
        .then(data => {
            // 保存登录时间
            setTimeStamp()
            resolve()
         })
      })
   }

utils/request 对应的请求拦截器中进行主动处理

import { isCheckTimeout } from '@/utils/auth'

if (store.getters.token) {
      if (isCheckTimeout()) {
        // 登出操作
        store.dispatch('user/logout')
        return Promise.reject(new Error('token 失效'))
      }
    }
  • 用户被动退出解决方案之被动处理

和用户主动退出一样,我们还是先了解一下背景以及业务逻辑

对于被动处理其实是有两种业务场景的

1、token 过期

对于 token 而言,本来就是有实效性的,这个在服务端生成 token 时就已经确定了,那么我们此时所说的 token 过期其实指的是服务端生成的 token 超过了我服务端设置的时效

2、单用户登录

用户 A 登录之后,在其 token 过期之前,用户 A 的账号在其他设备中进行了二次登录,导致第一次登录的 A 的账号被顶掉,即:同一账户仅可以在一个设备中保持在线

那么明确了对应的背景,我们再来看看对应的业务场景

从背景中我们知道,以上的两种情况,都是在服务端进行判断的,而对于前端而言其实是服务端通知前端的一个过程

所以说,我们的处理应该遵循如下的逻辑

1、服务端返回数据时,会通过特定的状态码通知前端

2、当前端接收到特定状态码时,表示遇到了特定状态:token 时效或单用户登录

3、此时进行退出登录处理

下边我们来看看对应的代码

在 utils/request 的响应拦截器中,增加以下逻辑:

// 响应拦截器
service.interceptors.response.use(
  response => {
  },
  error => {
    // 处理 token 超时问题
    if (
      error.response &&
      error.response.data &&
      error.response.data.code === 401
    ) {
      // token超时
      store.dispatch('user/logout')
    }
    ElMessage.error(error.message) // 提示错误信息
    return Promise.reject(error)
  }
)