登录页(-- 郑郑日上项目【vue-element-admin】【PC 端】【后台管理系统】)

1,181 阅读3分钟

(一)将 token 存储到 cookie 中

核心实现方式: 使用 js-cookie 插件将 token 存储到 cookie 中

1、通过 js-cookie 中的 getToken() 获取存储在 cookie 中的 token

(-- @/store/modules/user.js;state 配置项)

token: getToken()

2、通过 js-cookie 中的 setToken() 将 token 存储到 cookie 中 && 将 token 存储到 state 中

(-- 同上;mutations 配置项)

setToken(state, token) {
  state.token = token
  setToken(token)
}

(-- 同上;actions 配置项)

async login(context, data) {
  const result = await login(data)
  context.commit('setToken', result)
}

(-- @/views/login/index.vue)

import { mapActions } from 'vuex'

methods() {
  ...mapActions(['user/login'])
}

async login() { // 登录

  -- 增
  await this.$store.dispatch('user/login', this.loginForm)
  --

  this.$router.push({
    name: 'Dashboard'
  })
}

(二)每次发送请求时携带 token

核心实现方式: 在请求拦截器中的请求头中携带 token

(-- @/utils/request.js)

service.interceptors.request.use(config => { // 请求拦截器

  -- 增
  if (store.getters.token) { // 在请求头中携带 token
    config.headers['Authorization'] = `${store.getters.token}`
  }
  --

  return config
})

(三)token 过期时的处理

前端实现

核心实现方式: 获取 token 时,将当前时间戳一起存储到缓存中。每当发起请求时,判断(当前时间戳 - 缓存中的时间戳)/ 1000 如果大于过期时间,表示 token 过期,清空 token,跳转到登录页,抛出时间戳过期提示

1、定义时间戳的 key && 定义获取时间戳的方法 && 定义设置时间戳的方法

(-- @/utils/auth.js)

const timeKey = 'hrsaas-timestamp-key' // 时间戳

export function getTimeStamp() { // 获取 时间戳
  return Cookies.get(timeKey)
}
export function setTimeStamp() { // 设置 时间戳
  Cookies.set(timeKey, Date.now())
}

2、获取 token 的时候将当前时间戳存到缓存中

(-- @/views/login/index.vue)

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

async login(content, data) { // 登录
  ...
  context.commit('setToken', result)

  -- 增
  setTimeStamp()
  --

}

3、每次请求时,调用 判断 token 是否过期的方法,如果过期则清空 token,跳转到登录页,并抛出错误

(-- @/utils/request.js)

-- 增
import { getTimeStamp } from '@/utils/auto'
import router from '@/router'

const TimeOut = 3600 // token 过期时间。3600 毫秒 = 一小时

function IsCheckTimeOut() { // 判断 token 是否过期
  var currentTime = Date.now() // 当前时间戳
  var timeStamp = getTimeStamp() // 缓存时间戳
  return (currentTime - timeStamp) / 1000 > TimeOut // 判断 token 是否过期 // 公式:【(当前时间戳 - 缓存中的时间戳)/ 1000 如果大于过期时间,表示 token 过期】。这里的除 1000 是将毫秒转化成秒。
}
--

// 请求拦截器
if (store.getters.token) {

  -- 增
  if (IsCheckTimeOut()) { // 判断 token 是否过期
    store.dispatch('user/logout') // 调用登出方法
    router.push('/login')
    return Promise.reject(new Error('token 超时了'))
  }
  --

}

后端实现(推荐)

核心实现方式: 在响应拦截器中判断后端响应的状态码,如果是 401 则表示 token 过期,然后清空 token、和 vuex 中的 token 即可

(-- @/utils/request.js)

-- 增
import store from '@/store'
import router from '@/router'
--

// 响应拦截器
service.interceptors.response.use(response => {
  ...
}, error => {

  -- 增
  if (error.response && error.response.data && error.response.data.code === 10002) { // 判断 token 是否过期

    // 调用登出方法
    store.dispatch('user/logout')

    router.push('/login')
  } else {

    -- 改(新)
    Message.error(error.message) // 提示错误信息
    --

  }
  return Promise.reject(error)
  --

  -- 改(旧)
  Message.error(error.message) // 提示错误信息
})

(四)退出功能

核心实现方式: 1、清空 state 中的 token 2、清空 cookie 中的 token 3、清空 用户信息

(五)设置路由白名单和有 token 的情况下访问登录页直接跳转到首页

核心实现方式: 导航守卫。在前置守卫中(判断是否有 token(如果有 token 在通过前置守卫的第一个参数判断是否访问的是 登录页,如果是登录页则调用前置守卫的第三个参数跳转到首页))

(-- @/新建 permission.js)

import router from '@/router'
import nprogress from 'nprogress'
import 'nprogress/nprogress.css' // 引入进度条样式
import store from '@/store'

const whiteList = ['/login', '/404', '/demo'] // 白名单

router.beforeEach((to, from, next) => { // 前置守卫 // (参数一:将要 访问 路由的信息对象)(参数二:将要 离开 路由的信息对象)(参数三:是一个函数,表示放行,允许这次路由导航)
  nprogress.start() // 开启进度条

  if (store.getters.token) { // 判断 是否有 token
    if (to.path === '/login') { // 判断 是否前往 登录页
      next('/')
    } else {
      next()
    }
  } else {
    if (whiteList.includes(to.path)) { // 判断 前往的地址是否在白名单中
      next()
    } else {
      next('/login')
    }
  }

  nprogress.done() // 解决手动切换地址时,进度条不关闭的问题
})
router.afterEach(() => { // 后置守卫
  nprogress.done() // 关闭进度条
})